zoukankan      html  css  js  c++  java
  • POJ2752 Seek the Name, Seek the Fame [KMP]

      简单的KMP,考察对next数组的理解,next[i]表示S[1..i]中前缀和后缀的最大匹配程度。

      假设字符串长度为L,用S[i..j]表示下标从i到j的字符组成的子串。

      首先next[L]=x1,说明这个字符串S[1..x1]和S[L-x1+1..L]是相同的,所以x1是一个可能的公共前缀和后缀的长度值。然后next[x1]=x2,说明S[1..x2]和S[x1-x2+1..x1]是相等的,而S[1..x1]=S[L-x1+1..L],就有S[1..x2]=S[x1-x2+1..x1]=S[L-x2+1..L],所以x2也是一个可能的前缀和后缀的公共长度值,这样一直推到next[i]=0就可以了。

      next数组的这个特性好好利用可以解蛮多题目的。比如POJ2185,POJ1961等等。一般考KMP也就是考这个了。

    #include<cstdio>
    #include<string.h>
    using namespace std;
    char s[400005];
    int next[400005],ans[400005],anss;
    int main(){
    freopen("test.in","r",stdin);
        while(scanf("%s",s+1)!=EOF){
            next[1]=0;
            int len=strlen(s+1);
            for(int i=2,j=0;i<=len;i++){
                while(j>0&&s[i]!=s[j+1])j=next[j];
                if(s[i]==s[j+1])j++;
                next[i]=j;
            }
            anss=0;
            ans[anss++]=len;
            for(int i=len;next[i]!=0;i=next[i]){
                ans[anss++]=next[i];
            }
            for(int i=anss-1;i>=0;i--){
                printf("%d",ans[i]);
                if(i!=0)printf(" ");
            }
            printf("\n");
        }
        return 0;
    }
  • 相关阅读:
    信号与系统04 离散时间傅里叶变换
    什么是吉布斯现象
    部分分式展开
    常见的傅里叶变换对
    微分运算的时域扩展
    动态库和静态库的制作与使用 【转载】原文链接https://www.cnblogs.com/WindSun/p/11287927.html
    派生访问说明符
    自定义异常类
    C++虚函数
    Linux知识点
  • 原文地址:https://www.cnblogs.com/swm8023/p/2621451.html
Copyright © 2011-2022 走看看