您的位置:首页 > 其它

Manacher模板,kmp,扩展kmp,最小表示法模板

2013-07-30 22:47 274 查看
// Manacher算法,很好用。

char s[2*N]; //储存临时串
int save[2*N];//中间记录

int Manacher(char tmp[])
{
int len=strlen(tmp);
int cnt=0;
for(int i=0;i<len;i++)
{
s[cnt++]='#';
s[cnt++]=tmp[i];
}
s[cnt++]='#';
memset(save,0,sizeof(save));
int a=0,p=0;
int mx=1;
for(int i=1;i<cnt-1;i++)
{
if(i>=p)
{
int num=1;
while(i+num<cnt&&i-num>=0&&s[i+num]==s[i-num])
{
num++;
}
p=i+num-1; //能到达的最远位置
a=i;
save[i]=num-1; //从这个位置出发最长的回文
if(save[i]==0) continue;
if(s[i]=='#')
{
if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1);
}
else
{
if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1;
}
}
else
{
int j=2*a-i;
if( i+save[j] < p)
{
save[i]=save[j];
if(save[i]==0) continue;
if(s[i]=='#')
{
if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1);
}
else
{
if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1;
}
}
else
{
int k=2*i-p;
while(p+1<cnt&&k-1>=0&&s[p+1]==s[k-1])
{
p++;
k--;
}
a=i;
save[i]=p-i;
if(save[i]==0) continue;
if(s[i]=='#')
{
if(2*((save[i]-1)/2 +1)>mx) mx=2*((save[i]-1)/2+1);
}
else
{
if(2*(save[i]/2)+1>mx) mx=2*(save[i]/2)+1;
}
}
}
}
return mx;
}


kmp,扩展kmp

// 感觉kmp可以理解。

#define N 100010
int s
;
int next
;
int t
;

int main()
{
//freopen("//home//chen//Desktop//ACM//in.text","r",stdin);
//freopen("//home//chen//Desktop//ACM//out.text","w",stdout);
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
scanf("%d",s+i);
for(int i=0;i<m;i++)
scanf("%d",t+i);
///////////////求next
int j=0;
next[0]=0;
for(int i=1;i<m;i++)
{
while(j!=0&&t[j]!=t[i]) j=next[j-1];
if(t[j]==t[i]) j++;
next[i]=j;
}

/////////////////////

j=0;
int ans=-1;
for(int i=0;i<n;i++)
{
while(j!=0&&s[i]!=t[j]) j=next[j-1];
if(s[i]==t[j]) j++;
if(j==m)
{
ans=i+1-m+1;
break;
}
}

///////////////////
if(ans==-1)
printf("-1\n");
else
printf("%d\n",ans);
}
return 0;
}

// 扩展kmp。
#defien N 100100

int next
,sum
;// sum用来记录

void build(char s[])
{
memset(next,0,sizeof(next));
int p=0,a=0;
next[0]=len;
for(int i=1;i<len;i++)
{
if(i+next[i-a]-1<p)
{
next[i]=next[i-a];
}
else
{
int k=p-i;
while(p+1<len && s[p+1]==s[k+1])
{
p++; k++;
}
p=max(p,i);
next[i]=k+1;
a=i;
}
}
}

void extend_kmp(char s[],char t[])//求从s到t上的最大前缀
{
memset(sum,0,sizeof(sum));
int p=-1,a=0;
for(int i=0;i<len;i++)
{
if(i+next[i-a]-1<p)
{
sum[i]=next[i-a];
}
else
{
int k=p-i;
while(p+1<len && s[p+1]==t[k+1])
{
p++; k++;
}
p=max(p,i);
sum[i]=k+1;
a=i;
}
}
}


最小表示法

int mistr(char s[],int len)  //输入一串字符,返回最小表示法的起始位置
{
int i=0,j=1,k=0;
while(i<len&&j<len&&k<len)
{
if(s[i+k]==s[j+k])
{
k++;
}
else
{
if(s[i+k] > s[j+k]) i=i+k+1;
if(s[i+k] < s[j+k]) j=j+k+1;
k=0;
if(i==j) j++;
}
}
return min(i,j);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: