您的位置:首页 > 其它

KMP

2015-10-05 19:01 197 查看
// 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);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: