【字符串KMP】一些题?

POJ 2752  NameFame

利用失配数组nxt
最长的一个“前后缀”是1~nxt[n],那么下一个是多少?
#include<bits/stdc++.h>
using namespace std;
#define rg register
const int N=1000000+5,M=10000+5,inf=0x3f3f3f3f,P=99999997;
int l,j,cnt,nxt[N],ans[N];
char s[N];
int main(){
//    freopen("in2.txt","r",stdin);
    while(scanf("%s",s+1)==1){
        memset(nxt,0,sizeof(nxt));
        l=strlen(s+1),j=cnt=0;
        for(int i=2;i<=l;++i){
            while(j&&s[i]!=s[j+1]) j=nxt[j];
            if(s[i]==s[j+1]) ++j;
            nxt[i]=j;
        }
        int pos=l;
        while(nxt[pos])
            ans[++cnt]=nxt[pos],pos=nxt[pos];
        for(int i=cnt;i;--i) printf("%d ",ans[i]);
        printf("%d
",l);
    }
    return 0;
}

Power String 循环节

给定一个字符串,求它最短的循环节长度
考虑n-next[n]与n的关系
若n不是n-next[n]的倍数,如何证明最短循环节长度只能是1
假设S的长度为len,则S存在最小循环节,循环节的长度L为len-next[len],子串为S[0…len-next[len]-1]。

(1)如果len可以被len - next[len]整除,则表明字符串S可以完全由循环节循环组成,循环周期T=len/L。

(2)如果不能,说明还需要再添加几个字母才能补全。需要补的个数是循环个数L-len%L=L-(len-L)%L=L-next[len]%L,L=len-next[len]。

#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
#define rg register
const int N=1000000+5,M=10000+5,inf=0x3f3f3f3f,P=99999997;
int T,n,l,j,nxt[N],ans[N];
char s[N];
int main(){
//    freopen("in2.txt","r",stdin);
    scanf("%d",&T);
    while(scanf("%s",s+1)==1&&s[1]!='.'){
        memset(nxt,0,sizeof(nxt));
        n=strlen(s+1),j=0;
        for(int i=2;i<=n;++i){
            while(j&&s[j+1]!=s[i]) j=nxt[j];
            if(s[i]==s[j+1]) ++j;
            nxt[i]=j;
        }
        l=n-nxt[n];
        if(n%l) puts("1");
        else printf("%d
",n/l);
    }
    return 0;
}

POJ - 2185 Milking Grid

给定一个R*C的二维矩阵,其中C<= 75,求面积最小的长方形生成单元
例如:ABABA
ABABA 
则答案为2,即AB
思路:
对每一维分别做一次KMP,在做这一维时,将另一维整体看成字符
一维情况下,答案是n-next[n]
二维情况下,答案是(R-next[R])*(C-next[C])
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
#define Max(x,y) (x)>(y)?(x):(y)
#define Min(x,y) (x)>(y)?(y):(x)
#define ll long long
#define rg register
const int N=10000+5,M=10000+5,inf=0x3f3f3f3f,P=99999997;
int r,c,w=0,h=0,nxt[N],ans[N];
char s[N][N];

int KMP(int pos,int flag){
    memset(nxt,0,sizeof(nxt));
    int j=0,l;
    if(!flag){
        for(int i=2;i<=c;++i){
            while(j&&s[pos][j+1]!=s[pos][i]) j=nxt[j];
            if(s[pos][i]==s[pos][j+1]) ++j;
            nxt[i]=j;
        }
        return c-nxt[c];
    }
    else{
        for(int i=2;i<=r;++i){
            while(j&&s[j+1][pos]!=s[i][pos]) j=nxt[j];
            if(s[i][pos]==s[j+1][pos]) ++j;
            nxt[i]=j;
        }
        return r-nxt[r];
    }
}

int main(){
//    freopen("in2.txt","r",stdin);
    scanf("%d%d",&r,&c);
    for(int i=1;i<=r;++i) scanf("%s",s[i]+1);
    for(int i=1;i<=r;++i) w=Max(w,KMP(i,0));
    for(int i=1;i<=c;++i) h=Max(h,KMP(i,1));
    printf("%d
",w*h);
    return 0;
}
原文地址:https://www.cnblogs.com/lxyyyy/p/11253164.html