zoukankan      html  css  js  c++  java
  • 字符串 专题

    今天复习字符巛 还剩下一点时间  我先 打一下模板

    $ 1$  最小表示法

    贪心 首先把 $ S $ 复制一遍成一个环 

    然后定义两个指针  i j 从 i j 开始一次扩展 字符巛 的长度  即  从$0$ 的长度开始扩展到 $n-1$  ($k $最大到 $n$ >- 停止循环 找到答案)

    然后比较其中是否相等  

    如果不相等就跳过循环 

    判断 当前 $S[i+k]$ 与$S[j+k]$ 的 大小 因为中间的字符串 都相等 所以 指针可以跳到  $x+k+1$ 处 $[x|i,j]$ 

    然后因为 最小的指针一定不会移动到最大的指针的后面所以 答案为 $min(i,j)$

    $ i,j $只循环到 n 的位置 因为以后都是一样的 了 

    code;

    int i=1,j=2;
    int k=0;
    while(i<=n&&j<=n)
    {
            for(int k=0;k<n;k++)
        {
          if(S[i+k]!=S[j+k]) break;
        }
        if(k==n) break;
           if(s[i+k]>s[j+k]) i=i+k+1;
           else
        {
          if(s[i+k]<s[j+k]) j=j+k+1;
        }
        if(i==j) j++;
    }          
    cout<<min(i,j);

    2 .01 字典树

     作用 : 寻找异或最大值 

    方法 :

       插入: 每位每位地找 没有就扩展 扩展完之后 就插入

    code:

    void inset(int v)
    {
        int u=0;
        for(int i=32;i>=0;i--)
        {
            int k=(sum[v]>>i)&1;
            if(!ch[u][k])
            {
                ch[u][k]=tot++;
            }
            u=ch[u][k];
        }
        val[u]=sum[v];
    }

     寻找:从最高位 开始 搜寻 先找 不同的 后找相同的 注意 先插入 $sum[0]$ 保证有解 

          如果 找不到 就一定没有

    code:

    int find(int v)
    {
        int u=0;
        for(int i=32;i>=0;i--)
        {
            int k=(v>>i)&1;
            if(ch[u][k^1]) u=ch[u][k^1];
            else
            u=ch[u][k];
        }
        return val[u];
    }

    $3$ 状态很差,但是还是坚持来写下博客啦

    KMP

    作用 匹配或者最长字串

    首先 fail数组 记的是 前i位 的最长前缀和后缀 

    求fail 数组首先得与自己比对  注意得从第二位开始 求出回退值

    code:

    
            fail[0]=-1;
            int j=-1;
            for(int i=1;i<s[1].size();i++) 
            {
                while(j>-1&&(s[1][j+1]!=s[1][i])) j=fail[j];
                
                if(s[1][j+1]==s[1][i]) j++;
                fail[i]=j;
            }

    求匹配   匹配使得前后缀一样 就很强 从第一位开始

    int j=-1;
        int ans=0;
        fail[0]=-1;
        for(int i=0;i<s[v].size();i++)
        {
            while(j>-1&&(s[1][j+1]!=s[v][i])) {
                ans=max(ans,j);
            j=fail[j];}
            
            if(s[1][j+1]==s[v][i]) j++;
         if(j==m)
         {
         
            ans=max(j+1,ans);

         }
    } return ans;

    $@$求最长公共字串匹配

    找一个串 然后挨个匹配 找最小值 然后删除第一个元素 再次找最小值 最后取max 

    介绍一下动态数组的erase神操作

    #include<bits/stdc++.h>
    using namespace std;
    int n;
    string  s[8];
    int fail[3000];
    int  kmp(int v)
    {
        int j=-1;
        int ans=0;
        fail[0]=-1;
        for(int i=0;i<s[v].size();i++)
        {
            while(j>-1&&(s[1][j+1]!=s[v][i])) {
                ans=max(ans,j);
            j=fail[j];}
            
            if(s[1][j+1]==s[v][i]) j++;
    
                ans=max(ans,j+1);
        }
        return ans;
    }
    int main()
    {
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>s[i];
        }
        int aans=0;
        while(s[1].size())
        {
        int ans=100000000;
            fail[0]=-1;
            int j=-1;
            for(int i=1;i<s[1].size();i++) 
            {
                while(j>-1&&(s[1][j+1]!=s[1][i])) j=fail[j];
                
                if(s[1][j+1]==s[1][i]) j++;
                fail[i]=j;
            }
        for(int i=2;i<=n;i++)
        {
            
            ans=min(ans,kmp(i));
            
        }
           aans=max(aans,ans);
           s[1].erase(s[1].begin());
        }
        cout<<aans;
    }

      

    $@@$结论 字符串乘方 i%(i-fail[i])==0 那么一定有乘方 个数为$i/(i-fail[i])$

     $4$马拉车

    首先初始化 把回文串都变成奇数回文串

    类似于这样

    void init()
    {
        S[0]='#';
        S[1]='#';
    
        for(int i=0;i<strlen(s);i++)
        {
            S[++tot]=s[i];
            S[++tot]='#';
        }
        S[++tot]='';
        
    }

    一共由两种大情况 i 在已经更新的回文串maxlen 的右边或左边

    对于i在左边的情况 $r[i] =min|{r[2*p-i],maxlen-i+1}|$ 其中$2*p-i$是$i$ 关于$p $对称的回文对应位置

    对于i 在右边的情况 $r[i]=1$ 

         if(i<maxlen)
               r[i]=min(maxlen-i+1,r[2*P-i]);
            else
               r[i]=1;

    然后挨着扩展

    类似于这样

     while(S[i-r[i]]==S[i+r[i]])r[i]++;

    最后更新maxlen 和p 的$val$

         if(i+r[i]-1>maxlen)
             {
                 maxlen=i+r[i]-1;
                 P=i;
             }

    注意到r数组位是最长回文半径(包括自己)

    $r[i]-1$ 是原字符串的回文长度

             

    string 类型可以直接比较  字典序

    strcpy strcmp strlen 字符数组的函数

    刀剑映出了战士的心。而我的心,漆黑且残破
  • 相关阅读:
    LeetCode(287)Find the Duplicate Number
    LeetCode(290) Word Pattern
    LeetCode(205)Isomorphic Strings
    LeetCode(201) Bitwise AND of Numbers Range
    LeetCode(200) Number of Islands
    LeetCode(220) Contains Duplicate III
    LeetCode(219) Contains Duplicate II
    命令行执行Qt程序
    LeetCode(228) Summary Ranges
    redis 的安装和使用记录
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11338801.html
Copyright © 2011-2022 走看看