NOIP模板複習——字串
阿新 • • 發佈:2018-12-30
雜湊
直接用 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;
}