字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机
为何scanf("%s", str)不需要&运算 经常忘掉的字符串知识点,最好不加&,不加&最标准,指针如果像scanf里一样加&是错的,大概是未定义行为
马拉车
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=;
int n,siz;
char ch[maxn]={};
char ch1[maxn*]={};
int p[maxn*]={};
void fir(){
siz=n*+;
ch1[]='$';ch1[]='#';
for(int i=;i<=n;i++)ch1[i*]=ch[i-],ch1[i*+]='#';
ch1[siz]='\0';
}
int Manacher(){
fir();int x=,j=,ans=;
for(int i=;i<siz;i++){
if(x+j>i)p[i]=min(x+j-i+,p[x*-i]);
else p[i]=;
while(ch1[i+p[i]]==ch1[i-p[i]])p[i]++;
if(i+p[i]->x+j)x=i,j=p[i]-;
if(p[i]>ans)ans=p[i];
//cout<<i<<ch1[i]<<p[i]<<endl;
}
return ans-;
}
int main(){
int T;scanf("%d",&T);
while(T-->){//ch[i],ch1[i],p[i]似乎都不用清空,因为所有的用之前都已经被清一次了。
scanf("%s",ch);n=strlen(ch);
int ma=Manacher();
printf("%d\n",ma);
}
return ;
}
Manacher
kmp
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=;
int cn,sn;//模式串和主串的大小
char ch[maxn]={};//模式串
char st[maxn]={};//主串
int nex[maxn]={};
void kmp(){
int j=-,i=;
nex[]=-;
while(i<cn){
if(j==-||ch[i]==ch[j])nex[++i]=++j;
else j=nex[j];
}
}
int get_id(){//在主串中第一次出现的位置
int i=,j=;
while(i<sn&&j<cn){
if(j==-||ch[j]==st[i]){i++;j++;}
else j=nex[j];
}
if(j==cn)return i-cn;
else return -;
}
int get_count(){//在主串中出现的次数
int i,j=,cnt=;
for(i=;i<sn;i++){
while(j>&&st[i]!=ch[j]) j=nex[j];
if(st[i]==ch[j])j++;
if(j==cn){cnt++;j=nex[j];}
}
return cnt;
}
int main(){
int T;scanf("%d",&T);
while(T-->){
scanf("%s",ch);cn=strlen(ch);
scanf("%s",st);sn=strlen(st);
kmp();
printf("%d %d\n",get_id(),get_count());
}
return ;
}
kmp
ac自动机(在poj2222提交的时候wa了好几次后来发现没有清空,而且这次重新打发现了自己之前写的漏洞。。。)
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=;
int n,siz;
char ch[]={};
char str[maxn*]={};
struct trie{
int sig[];
int cnt;
int vis;
int fail;
}t[maxn*];int tot=;
int q[maxn*]={};int head=,tail=;
void fir(){
tot=;memset(t,,sizeof(t));//memset(q,0,sizeof(q));
}
void init(int x,int j){
if(j>siz-){ t[x].cnt++; return; }
int z=ch[j]-'a';
if(!t[x].sig[z])t[x].sig[z]=++tot;
init(t[x].sig[z],j+);
}
void build_fail(){
int head=,tail=,x,y,f;q[]=;
while(head<=tail){
x=q[head++];
for(int i=;i<;i++)
if(t[x].sig[i]){
y=t[x].sig[i];
if(x){
f=t[x].fail;
while((!t[f].sig[i])&&f)
f=t[f].fail;
t[y].fail=t[f].sig[i];
}q[++tail]=y;
}
}
}
int get_num(){//字符串中包含的单词数量,重复的不记录,
//如果单词x在字符串中出现一次而在单词表中有两个则ans+2
//在字符串中出现两次而单词表中有一个则ans+1
int ans=,x=,y,z;
for(int i=;i<siz;i++){
z=str[i]-'a';
while((!t[x].sig[z])&&x)
x=t[x].fail;
x=t[x].sig[z];y=x;
while(y&&(!t[y].vis)){//保证了每个结尾只访问一次
ans+=t[y].cnt;
t[y].vis=;t[y].cnt=;
y=t[y].fail;
}
}
return ans;
}
int main(){
int T;scanf("%d",&T);
while(T-->){
fir();
scanf("%d",&n);
for(int i=;i<=n;i++){scanf("%s",ch);siz=strlen(ch);init(,);}
build_fail();
scanf("%s",str);siz=strlen(str);
printf("%d\n",get_num());
}
return ;
}
AC自动机
后缀数组 每次都l=<<2然后调错,我大概是个zz。一定要分清楚*2和<<1啊
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
using namespace std;
const int maxn=;
const int pl=;
int siz;
char ch[maxn+pl]={};
int p[maxn+pl]={},sa[maxn+pl]={},rk[maxn+pl]={};
int cnt[maxn+pl]={},temp[maxn+pl]={},height[maxn+pl]={};
bool equ(int x,int y,int l){return rk[x]==rk[y]&&rk[x+l]==rk[y+l];}
void SA(){
for(int i=;i<=siz;i++)sa[i]=i,rk[i]=ch[i];
for(int i,sig=,pos=,l=;pos<siz;sig=pos){
pos=;
for(i=siz-l+;i<=siz;i++)p[++pos]=i;
for(i=;i<=siz;i++)if(sa[i]>l)p[++pos]=sa[i]-l;
for(i=;i<=sig;i++)cnt[i]=;
for(i=;i<=siz;i++)cnt[rk[p[i]]]++;
for(i=;i<=sig;i++)cnt[i]+=cnt[i-];
for(i=siz;i>;i--) sa[cnt[rk[p[i]]]--]=p[i];
pos=;
for(i=;i<=siz;i++){
if(equ(sa[i],sa[i-],l))temp[sa[i]]=pos;
else temp[sa[i]]=++pos;
}
for(i=;i<=siz;i++)rk[i]=temp[i];
if(!l)l=;
else l<<=;
}
int j=;
for(int i=;i<=siz;i++){
if(rk[i]==){j=;continue;}
if(j)j--;
while(ch[i+j]==ch[sa[rk[i]-]+j])j++;
height[rk[i]]=j;
}
}
int main(){
scanf("%s",ch+);
siz=strlen(ch+);
SA();
for(int i=;i<=siz;i++)printf("%d ",sa[i]);
cout<<endl;
for(int i=;i<=siz;i++)printf("%d ",height[i]);
cout<<endl;
return ;
}
后缀数组
后缀自动机,相对于它的名气好写。但是有时候还是会在犯zz错误 这里的代码copy过来了
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
const int maxn=;
char ch1[maxn]={},ch2[maxn]={};
int siz1,siz2;
struct nod{
int sig[];
int f,len;
}t[maxn*];int tot=,la=;
void add(int z){
int x=++tot;int i=la;
t[x].len=t[la].len+;
for(;i&&!t[i].sig[z];i=t[i].f)
t[i].sig[z]=x;
if(!i)t[x].f=;
else{
int p=t[i].sig[z];
if(t[p].len==t[i].len+)t[x].f=p;
else{
int y=++tot;
t[y]=t[p];t[y].len=t[i].len+;
t[x].f=t[p].f=y;
for(;i&&t[i].sig[z]==p;i=t[i].f){
t[i].sig[z]=y;
}
}
}
la=x;
}
int main(){
memset(t,,sizeof(t));
scanf("%s",ch1+);
scanf("%s",ch2+);
siz1=strlen(ch1+);
siz2=strlen(ch2+);
for(int i=;i<=siz1;i++)add(int(ch1[i]-'a'));
int ans=,j=,tmp=;
for(int i=;i<=siz2;i++){
int z=ch2[i]-'a';
if(t[j].sig[z]){j=t[j].sig[z];tmp++;}
else{
while(j&&!t[j].sig[z])
j=t[j].f;
if(!j){j=;tmp=;}
else {tmp=t[j].len+;j=t[j].sig[z];}
}
if(tmp>ans)ans=tmp;
}printf("%d\n",ans);
return ;
}
SAM
字符串的模板 Manacher kmp ac自动机 后缀数组 后缀自动机的更多相关文章
- 【整理】如何选取后缀数组&&后缀自动机
		后缀家族已知成员 后缀树 后缀数组 后缀自动机 后缀仙人掌 后缀预言 后缀Splay ? 后缀树是后缀数 ... 
- loj6173 Samjia和矩阵(后缀数组/后缀自动机)
		题目: https://loj.ac/problem/6173 分析: 考虑枚举宽度w,然后把宽度压位集中,将它们哈希 (这是w=2的时候) 然后可以写一下string=“ac#bc” 然后就是求这个 ... 
- (17/34)AC自动机/后缀数组/后缀自动机(施工中)
		快补题别再摸鱼了(17/34) 1.AC自动机 #define maxnode 1000010 #define maxsize 26 struct ahocT{ int ch[maxnode][max ... 
- POJ - 2774 Long Long Message (后缀数组/后缀自动机模板题)
		后缀数组: #include<cstdio> #include<algorithm> #include<cstring> #include<vector> ... 
- luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分
		仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ... 
- SPOJ694 DISUBSTR --- 后缀数组 / 后缀自动机
		SPOJ694 DISUBSTR 题目描述: Given a string, we need to find the total number of its distinct substrings. ... 
- POJ2774Long Long Message (后缀数组&后缀自动机)
		问题: The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to ... 
- POJ1743  Musical Theme (后缀数组 & 后缀自动机)最大不重叠相似子串
		A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ... 
- SPOJ- Distinct Substrings(后缀数组&后缀自动机)
		Given a string, we need to find the total number of its distinct substrings. Input T- number of test ... 
随机推荐
- 【BZOJ】1355 [Baltic2009]Radio Transmission
			[算法]KMP [题解]KMP中n-next[n]得到最小循环节的性质. 考虑一个循环串(最后一个循环节可能残缺),它最长的[后缀=前缀]一定是以第二个循环节为起始位置的后缀. 正着考虑的话假设后缀T ... 
- Traffic-Server配置(待补充和更新)
			Server 5.3.2 测试1.裸盘:remap.configmap http://192.168.227.131 http://192.168.227.131:8080 #traffic_serv ... 
- Sublime text 2/3 SVN插件及使用方法
			Sublime Text是前端利器,作为前端的盆友们已经再熟悉不过了,在项目中经常使用SVN,每次都要切换提交,很麻烦,有了这个SVN插件就很方便了,使用快捷方式提交,更新. Sublime Text ... 
- 选择问题(选择数组中第K小的数)
			由排序问题可以引申出选择问题,选择问题就是选择并返回数组中第k小的数,如果把数组全部排好序,在返回第k小的数,也能正确返回,但是这无疑做了很多无用功,由上篇博客中提到的快速排序,稍稍修改下就可以以较小 ... 
- python并发编程之Queue线程、进程、协程通信(五)
			单线程.多线程之间.进程之间.协程之间很多时候需要协同完成工作,这个时候它们需要进行通讯.或者说为了解耦,普遍采用Queue,生产消费模式. 系列文章 python并发编程之threading线程(一 ... 
- flask基础之jijia2模板使用基础(二)
			前言 在以前前后端不分离的时代,后台程序员往往又当爹又当妈,需要将前端程序员写的h5页面填充模板语言.而jijia2是一门十分强大的python的模板语言,是flask框架的核心模块之一.先简单介绍一 ... 
- sar命令使用【转】
			sar(System Activity Reporter系统活动情况报告)是目前 Linux 上最为全面的系统性能分析工具之一,可以从多方面对系统的活动进行报告,包括:文件的读写情况.系统调用的使用情 ... 
- 121.Best Time to Buy and Sell Stock---dp
			题目链接:https://leetcode.com/problems/best-time-to-buy-and-sell-stock/description/ 题目大意:给出一串数组,找到差值最大的差 ... 
- B2旅游签证记
			先去https://ceac.state.gov/ceac/,选择DS-160表格,在线申请登记个人信息 ,选择大事馆“CHINA BEIJING”和验证码,点 Start an Applicatio ... 
- Linux 上配置 NTP SERVER
			在CENTOS 6.2上面安装配置NTP SERVER 安装NTP:yum install ntp 配置时间源vi /etc/ntp.confserver 210.72.145.44server nt ... 
