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 字符数组的函数

    刀剑映出了战士的心。而我的心,漆黑且残破
  • 相关阅读:
    CSS媒体查询
    搜索关键词标注红色
    揭秘 | 小白如何0基础0元建站
    细说浏览器输入URL后发生了什么
    js问题总结
    vue elementui如何修改el-table头部样式
    h5开发微信公众号重定向到关注页面没有关注按钮 (微信你个坑)
    下拉展开动画
    html中常用的转义字符总结
    9个设计师常用的高清图库 不敢配图? 这9个免版权图库牢记心中!
  • 原文地址:https://www.cnblogs.com/OIEREDSION/p/11338801.html
Copyright © 2011-2022 走看看