集合一下最近做题用到的模板,都是字符串相关的。
//kmp算法:
//优化版:
void GetNextval(string P, int nextval[])
{
int p_len = P.size();
int i = 0; //P的下标
int j = -1;
nextval[0] = -1;
while (i < p_len)
{
if (j == -1 || P[i] == P[j])
{
i++;
j++;
if (P[i] != P[j])
nextval[i] = j;
else
nextval[i] = nextval[j]; //既然相同就继续往前找真前缀
}
else
j = nextval[j];
}
}
//未优化版
void get_next(char a[])
{
int l=strlen(a);
int i=0;
int j=-1;
next[0]=-1;
while(i<l)
{
if(j==-1||a[i]==a[j])
{
i++;
j++;
next[i]=j;
}
else
j=next[j];
}
}
int kmp(char s[],char t[])
{
int ls=strlen(s);
int lt=strlen(t);
int j=0;
int i=0;
get_next(s);
while(i<lt&&j<ls)
{
if(j==-1||s[j]==t[i])
{
i++;
j++;
}
else
j=next[j];
}
if(j==ls) //匹配成功返回第一次出现的位置
return i-j;
return 0;
}
//扩展kmp算法(1):
void GETNEXT(char *str)
{
int i=0,j,po,len=strlen(str);
next[0]=len;//初始化next[0]
while(str[i]==str[i+1]&&i+1<len)//计算next[1]
i++;
next[1]=i;
po=1;//初始化po的位置
for(i=2;i<len;i++)
{
if(next[i-po]+i<next[po]+po)//第一种情况,可以直接得到next[i]的值
next[i]=next[i-po];
else//第二种情况,要继续匹配才能得到next[i]的值
{
j=next[po]+po-i;
if(j<0)j=0;//如果i>po+next[po],则要从头开始匹配
while(i+j<len&&str[j]==str[j+i])//计算next[i]
j++;
next[i]=j;
po=i;//更新po的位置
}
}
}
//计算extend数组
void EXKMP(char *s1,char *s2)
{
int i=0,j,po,len=strlen(s1),l2=strlen(s2);
GETNEXT(s2);//计算子串的next数组
while(s1[i]==s2[i]&&i<l2&&i<len)//计算ex[0]
i++;
ex[0]=i;
po=0;//初始化po的位置
for(i=1;i<len;i++)
{
if(next[i-po]+i<ex[po]+po)//第一种情况,直接可以得到ex[i]的值
ex[i]=next[i-po];
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])//计算ex[i]
j++;
ex[i]=j;
po=i;//更新po的位置
}
}
}
//扩展kmp算法(2):
void GetNext(string & T, int & m, int next[])
{
int a = 0, p = 0;
next[0] = m;
for (int i = 1; i < m; i++)
{
if (i >= p || i + next[i - a] >= p)
{
if (i >= p)
p = i;
while (p < m && T[p] == T[p - i])
p++;
next[i] = p - i;
a = i;
}
else
next[i] = next[i - a];
}
}
/* 求解 extend[] */
void GetExtend(string & S, int & n, string & T, int & m, int extend[], int next[])
{
int a = 0, p = 0;
GetNext(T, m, next);
for (int i = 0; i < n; i++)
{
if (i >= p || i + next[i - a] >= p) // i >= p 的作用:举个典型例子,S 和 T 无一字符相同
{
if (i >= p)
p = i;
while (p < n && p - i < m && S[p] == T[p - i])
p++;
extend[i] = p - i;
a = i;
}
else
extend[i] = next[i - a];
}
}
//manacher算法:
void manacher(char *s)
{
int len=strlen(s);
for(int i=len;i>=0;--i){
s[i+i+2]=s[i];
s[i+i+1]='#';
}
s[0]='*';
int k=1,maxlen=0;
for(int i=2;i<len+len+1;++i){
int maxr=k+p[k]-1;
p[i]=min(p[2*k-i],max(maxr-i+1,1));
while(s[i-p[i]] == s[i+p[i]])++p[i];
if(i+p[i]>k+p[k])k=i;
if(p[i]>maxlen)maxlen=p[i];
}
}
//最大最小表示法:
int get_max_min(char s[],int flag)
{
int i=0;
int j=1;
int len=strlen(s);
int k=0;
while(i<len&&j<len&&k<len)
{
int t=s[(j+k)%len]-s[(i+k)%len];
if(t==0)
k++;
else
{
if(flag)
{
if(t>0) j+=k+1;
else i+=k+1;
}
else
{
if(t>0) i+=k+1;
else j+=k+1;
}
if(i==j) j++;
k=0;
}
}
return min(i,j);
}