哈希
直接用 unsigned long long,让它自然溢出(对 取模)就行了
对一个字符串哈希( 是哈希值, 是基数, 是字符串长度, 是第 个字符):
#define ull unsigned long long
ull Hash()
{
ull ans=0;
for(int i=0;i<l;++i)
ans=ans*base+s[i];
return ans;
}
当然,为了使正确性更高,可以用两个哈希或者甚至更多个哈希
KMP
A 是模式串,B 是匹配串,n 是 A 的长度,m 是 B 的长度
输出为 B 在 A 中所有能够匹配上的第一个位置(下标都是从 开始)
void init()
{
int i,j=0;
for(i=2;i<=m;++i)
{
while(j&&B[i]!=B[j+1]) j=nxt[j];
if(B[i]==B[j+1]) ++j;
nxt[i]=j;
}
}
void work()
{
int i,j=0;
for(i=1;i<=n;++i)
{
while(j&&A[i]!=B[j+1]) j=nxt[j];
if(A[i]==B[j+1]) ++j;
if(j==m)
{
j=nxt[j];
printf("%d\n",i-m+1);
}
}
}
Trie 树
以找前缀的数量为例吧
存储
struct Trie
{
int son[26];
int num;
}a[N];
插入( 是节点编号, 是要插入的字符串)
void Insert()
{
int l,i,p=0;
l=strlen(s);
for(i=0;i<l;++i)
{
if(a[p].son[s[i]-'a']==0)
a[p].son[s[i]-'a']=++t;
p=a[p].son[s[i]-'a'];
a[p].num++;
}
}
查询
int find()
{
int l,i,p=0;
l=strlen(s);
for(i=0;i<l;++i)
{
if(a[p].son[s[i]-'a']==0)
return 0;
p=a[p].son[s[i]-'a'];
}
return a[p].num;
}
如果直接 memset 清零的话可能会比较慢,可以边做的时候边清空,这样会快一点
Manacher
int R[N<<1];
char Old[N],New[N<<1];
int init()
{
int i,l,j=2;
scanf("%s",Old);
l=strlen(Old);
New[0]='$';
New[1]='#';
for(i=0;i<l;++i)
{
New[j++]=Old[i];
New[j++]='#';
}
New[j]='\0';
return j;
}
int manacher()
{
int i,l,p,m=0,Max=0;
l=init();
for(i=1;i<l;++i)
{
if(i>=m) R[i]=1;
else R[i]=min(R[2*p-i],m-i);
while(New[i-R[i]]==New[i+R[i]]) R[i]++;
if(m<i+R[i]) {m=i+R[i];p=i;}
Max=max(Max,R[i]-1);
}
return Max;
}