poj2752(exkmp)

題目鏈接:http://poj.org/problem?id=2752

思路:我當成exkmp模板做的,別的做法應該也行,這題和符合exkmp next數組的定義

定義母串S,和字串T,設S的長度爲n,T的長度爲m,求T與S的每一個後綴的最長公共前綴,也就是說,設extend數組,extend[i]表示T與S[i,n-1]的最長公共前綴,要求出所有extend[i](0<=i<n)。

next[i]表示T[i,m-1]和T的最長公共前綴長度。

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <bitset>
#include <cmath>
#include <cctype>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
#include <sstream>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef vector<long long> VI;
typedef unsigned long long ull;
const ll inff = 0x3f3f3f3f3f3f3f3f;
#define FOR(i,a,b) for(int i(a);i<=(b);++i)
#define FOL(i,a,b) for(int i(a);i>=(b);--i)
#define SZ(x) ((long long)(x).size())
#define REW(a,b) memset(a,b,sizeof(a))
#define inf int(0x3f3f3f3f)
#define si(a) scanf("%d",&a)
#define sl(a) scanf("%lld",&a)
#define sd(a) scanf("%lf",&a)
#define ss(a) scanf("%s",a)
#define mod ll(1e9+7)
#define pb push_back
#define eps 1e-6
#define lc d<<1
#define rc d<<1|1
#define Pll pair<ll,ll>
#define P pair<int,int>
#define pi acos(-1)
int n;
const int maxn=400010;   //字符串長度最大值
int ne[maxn],ex[maxn]; //ex數組即爲extend數組
char a[maxn];
//預處理計算next數組
void gne(char *str)
{
    int i=0,j,po,len=strlen(str);
    ne[0]=len;//初始化next[0]
    while(str[i]==str[i+1]&&i+1<len) i++;//計算next[1]
    ne[1]=i;po=1;//初始化po的位置
    for(i=2;i<len;i++)
    {
        if(ne[i-po]+i<ne[po]+po) ne[i]=ne[i-po];//第一種情況,可以直接得到next[i]的值
        else//第二種情況,要繼續匹配才能得到next[i]的值
        {
            j=ne[po]+po-i;
            if(j<0) j=0;//如果i>po+next[po],則要從頭開始匹配
            while(i+j<len&&str[j]==str[j+i]) j++;//計算next[i]
            ne[i]=j;po=i;//更新po的位置
        }
    }
}
//計算extend數組
void exkmp(char *s1,char *s2)
{
    int i=0,j,po,len=strlen(s1),l2=strlen(s2);
    gne(s2);//計算子串的next數組
    while(s1[i]==s2[i]&&i<l2&&i<len) i++;//計算ex[0]
    ex[0]=i;po=0;//初始化po的位置
    for(i=1;i<len;i++)
    {
        if(ne[i-po]+i<ex[po]+po) ex[i]=ne[i-po];//第一種情況,直接可以得到ex[i]的值
        else//第二種情況,要繼續匹配才能得到ex[i]的值
        {
            j=ex[po]+po-i;
            if(j<0)j=0;//如果i>ex[po]+po則要從頭開始匹配
            while(i+j<len&&j<l2&&s1[j+i]==s2[j]) j++;//計算ex[i]
            ex[i]=j;po=i;//更新po的位置
        }
    }
}
int main()
{
    cin.tie(0);
    cout.tie(0);
    while(ss(a)!=EOF)
    {
        gne(a);int l=strlen(a);
        FOL(i,l-1,0)
         if(ne[i]==l-i) printf("%d ",l-i);
        puts("");
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章