KMP

// hdu 1358前綴是由幾個循環串組成  next數組的運用  next[i]數組是後綴與前綴的最大相匹配的字符個數

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pp;
#define inf 0x3f3f3f3f
#define eps 1e-10
#define maxl 1000010
#define mem(i,j) memset(i,j,sizeof(i))
const int mod=1e9+7;
char s[maxl];
int n,jump[maxl];
void get_next(){
    jump[1]=0;
    int k=0;
    for(int i=2;i<=n;i++){
        while(k>0&&s[k+1]!=s[i]) k=jump[k];
        if(s[k+1]==s[i]) k+=1;
        jump[i]=k;
    }
}

int main()
{
    freopen("in.txt", "r", stdin);
    int t=0;
    while(scanf("%d",&n)&&n){
        printf("Test case #%d\n",++t);
        scanf("%s",s+1);
        get_next();    
        for(int i=2;i<=n;i++){
            if(jump[i]&&i%(i-jump[i])==0){
                printf("%d %d\n",i,i/(i-jump[i]));
            }
        }
        printf("\n");
    }
}





//P UVA 11475   補全字符串  使得這個是迴文字符串  但是補的字符最少   這是暴力的做法  KMP的還有待學習
/*
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef long long ll;
typedef pair<int,int> pp;
#define inf 0x3f3f3f3f
#define eps 1e-10
#define maxl 1000010
#define mem(i,j) memset(i,j,sizeof(i))
const int mod=1e9+7;
char s[maxl];
int main()
{
    freopen("in.txt", "r", stdin);
    while(gets(s)){
        int len=strlen(s);
        for(int i=0;i<len;i++){
            int l=i,r=len-1;
            int flag=1;
            for(int j=0;j<=(r-l+1)/2;j++) if(s[l+j]!=s[r-j]) {flag=0;break;}
            if(flag){
                printf("%s",s);
                for(int j=i-1;j>=0;j--) printf("%c",s[j]);
                printf("\n");
                break;
            }
        }
    }
}
*/

//O UVA 12886二維的KMP  但是隻有黑白倆種  hash   小矩形和大矩形 <=2000  hash打法 可以處理的情況很大的時候

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<vector>
using namespace std;
typedef unsigned long long ll;  
typedef pair<int,int> pp;
#define inf 0x3f3f3f3f
#define eps 1e-10
#define maxl 2020
#define mem(i,j) memset(i,j,sizeof(i))
const int mod=1e9+7;
const ll seed1=10000007;
const ll seed2=100000007;
char s1[maxl][maxl],s2[maxl][maxl];
ll hash1[maxl][maxl],hash2[maxl][maxl],h;
int x,y,n,m,ans;
ll get_hash(){  //預處理小矩形
    ll cnt=0,res;
    for(int i=0;i<x;i++){
        res=0;
        for(int j=0;j<y;j++)
            res=res*seed1+s1[i][j];//處理行
        cnt=cnt*seed2+res;//處理列
    }
    return cnt;
}

void solve(){
    ans=0;
    ll c=1;
    for(int i=0;i<y;i++) c=c*seed1;//這個是hash種子   y次seed1
    for(int i=0;i<n;i++){
        ll res=0;
        for(int j=0;j<y;j++) //這裏的0是y-1次seed1 剛好對應下面的
            res=res*seed1+s2[i][j];//處理相同長度的目標矩形的行
        hash1[i][y-1]=res;//用hash1來保存
        for(int j=y;j<m;j++){
            hash1[i][j]=hash1[i][j-1]*seed1-s2[i][j-y]*c+s2[i][j];//用DP的思想 來遞歸
        }
    }
    c=1;
    for(int i=0;i<x;i++) c=c*seed2;
    for(int i=y-1;i<m;i++){
        ll cnt=0;
        for(int j=0;j<x;j++)
            cnt=cnt*seed2+hash1[j][i];
        if(cnt==h) ans++;
        hash2[x-1][i]=cnt;
        for(int j=x;j<n;j++){
            hash2[j][i]=hash2[j-1][i]*seed2-hash1[j-x][i]*c+hash1[j][i];
            if(hash2[j][i]==h) ans++;
        }
    }
}

int main()
{
    freopen("in.txt", "r", stdin);
    while(scanf("%d%d%d%d",&x,&y,&n,&m)!=EOF){
        memset(hash1,0,sizeof(hash1));
        memset(hash2,0,sizeof(hash2));
        for(int i=0;i<x;i++) scanf("%s",s1[i]);
        for(int i=0;i<n;i++) scanf("%s",s2[i]);
        h=get_hash();
        solve();
        printf("%d\n",ans);
    }
}



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