为何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自动机 后缀数组 后缀自动机的更多相关文章

  1. 【整理】如何选取后缀数组&&后缀自动机

    后缀家族已知成员         后缀树         后缀数组         后缀自动机         后缀仙人掌         后缀预言         后缀Splay ? 后缀树是后缀数 ...

  2. loj6173 Samjia和矩阵(后缀数组/后缀自动机)

    题目: https://loj.ac/problem/6173 分析: 考虑枚举宽度w,然后把宽度压位集中,将它们哈希 (这是w=2的时候) 然后可以写一下string=“ac#bc” 然后就是求这个 ...

  3. (17/34)AC自动机/后缀数组/后缀自动机(施工中)

    快补题别再摸鱼了(17/34) 1.AC自动机 #define maxnode 1000010 #define maxsize 26 struct ahocT{ int ch[maxnode][max ...

  4. POJ - 2774 Long Long Message (后缀数组/后缀自动机模板题)

    后缀数组: #include<cstdio> #include<algorithm> #include<cstring> #include<vector> ...

  5. luoguP5108 仰望半月的夜空 [官方?]题解 后缀数组 / 后缀树 / 后缀自动机 + 线段树 / st表 + 二分

    仰望半月的夜空 题解 可以的话,支持一下原作吧... 这道题数据很弱..... 因此各种乱搞估计都是能过的.... 算法一 暴力长度然后判断判断,复杂度\(O(n^3)\) 期望得分15分 算法二 通 ...

  6. SPOJ694 DISUBSTR --- 后缀数组 / 后缀自动机

    SPOJ694 DISUBSTR 题目描述: Given a string, we need to find the total number of its distinct substrings. ...

  7. POJ2774Long Long Message (后缀数组&后缀自动机)

    问题: The little cat is majoring in physics in the capital of Byterland. A piece of sad news comes to ...

  8. POJ1743 Musical Theme (后缀数组 & 后缀自动机)最大不重叠相似子串

    A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ...

  9. SPOJ- Distinct Substrings(后缀数组&后缀自动机)

    Given a string, we need to find the total number of its distinct substrings. Input T- number of test ...

随机推荐

  1. NYOJ 163 Phone List (字符串处理 字典树)

    题目链接 描述 Given a list of phone numbers, determine if it is consistent in the sense that no number is ...

  2. 服务器端包含 SSI简介

    服务器端包含 SSI,是英文 Server Side Includes的简写.SSI是一种可以指挥服务器动态声称网页内容的HTML指令. 通常SSI可以用来确保网页中的一些通用内容,比如版权信息.联系 ...

  3. ValueList用法

    ValueList的OverView 概述 在很多情况下,使用JDBC是很繁琐的,有很多方法可以替换JDBC,比如JDO.Hibernate等. 即使在从service中接收POJO的List的解决方 ...

  4. CentOS测网速

    当发现上网速度变慢时,人们通常会先首先测试自己的电脑到网络服务提供商(通常被称为"最后一公里")的网络连接速度.在可用于测试宽带速度的网站中,Speedtest.net也许是使用最 ...

  5. python实战===python程序打包成exe

    推荐PyInstaller项目www.pyinstaller.org   安装方法: 先跑pip install pywin32再跑pip install pyinstaller即可 可用一句命令打包 ...

  6. 简单实现JS上传图片预览功能

    HTML代码 <div class="upload"> <input type="button" class="btn" ...

  7. 连接数据库:ERROR:The server time zone value '?й???????' is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration prop

    本打算在maven项目中配置mybatis试试看,想到mybatis如果不是在容器中运行,那么他的事务控制实际上可以使用的是jdbc的提交和回滚,这就要在pom.xml文件中配置mysql-conne ...

  8. Linux平台上SQLite数据库教程(一)——终端使用篇

    https://blog.csdn.net/u011192270/article/details/48031763 https://blog.csdn.net/fml1997/article/deta ...

  9. JS模块化规范AMD之RequireJS

    1.基本操作 加载 JavaScript 文件(入口文件) RequireJS以一个相对于baseUrl的地址来加载所有的代码 <script data-main="scripts/m ...

  10. MINIBASE源代码阅读笔记之buffer manager

    BufDesc frame 们的 descriptor(见BufHashTbl注释),包括 pageNo: 这个 frame 在文件里的id,page number prevframe: -1 表示此 ...