目录

  • 字符串
  • 经验
    • 用FFT求解字符串匹配问题
    • 两(多)串DP时状态合并
    • 最长公共子序列转LIS
    • 位运算最大值
    • 挂链哈希
    • 哈希处理回文串
    • 树哈希
  • 字符串模板库
    • KMP
    • 最小循环表示
    • Mancher
    • AC自动机
    • 后缀数组
    • 后缀自动机

字符串

Tags:Noip前的大抱佛脚

经验

用FFT求解字符串匹配问题

  • 一一对应

把其中一个\(Reverse\)后,对于每个字符跑一遍FFT,打上\(Tag\)
如果在某个位置上有串长个\(Tag\)那便是匹配上了一处

  • 模糊匹配

\(Fuzzy Search\) 在跑\(FFT\)前把模糊门限值的区间内全部置为1,然后同样的操作

两(多)串DP时状态合并

插入AC自动机,老套路了

最长公共子序列转LIS

求两个串的最长公共子序列,把第二个串的每个值映射到第一个串上 该值的位置
然后对第二个串求LIS即可(最长公共子串就是第二个串的最长连续段)

位运算最大值

异或最大值:建Trie贪心
与最大值:建Trie贪心(1的儿子siz大于2则走)/高维前缀和逐位贪心
或最大值:高维前缀和逐位贪心

但是求(x+B)^A的最大值呢(SCOI2016美味)(当然&操作也是一样的,这种题通常值域很小)
同样贪心地做
开值域线段树,贪心到某一位,需要该位为0或者1,则对应地可以算出x的范围,查询是否有在这个范围之内的x即可

挂链哈希

期望\(O(1)\),当然支持查询多个关键字

const int Mo=YYB;
struct HashTable
{struct Line{int next,val;}a[Mo];int head[Mo],cnt;void reset() {memset(head,0,sizeof(head));cnt=0;}void Add(int p,int val) {a[++cnt]=(Line){head[p],val};head[p]=cnt;}int Query(int x){for(int i=head[x%Mo];i;i=a[i].next)if(a[i].val==x) return 1;return 0;}
}Hash;

哈希处理回文串

正反哈希前缀和即可求出区间哈希值,然后查询起点到回文中心的正哈希和回文中心到终点的反哈希即可

树哈希

例:一棵无根树的本质不同的独立集个数(\(k\)棵相同子树方案为\(x\)则乘一个可重组合)

字符串模板库

KMP

【模板】KMP字符串匹配
用于两串匹配问题,做法是对子串求next后匹配母串,复杂度\(O(n+m)\)

const int N=1e6+10;
char s1[N],s2[N];
int nxt[N];
int main()
{scanf("%s%s",s1+1,s2+1);int l1=strlen(s1+1),l2=strlen(s2+1);for(int i=2;i<=l2;i++){int j=nxt[i-1];while(j&&s2[j+1]!=s2[i]) j=nxt[j];nxt[i]=(s2[j+1]==s2[i])+j;}for(int i=1,j=0;i<=l1;i++){while(j&&s2[j+1]!=s1[i]) j=nxt[j];if(s2[j+1]==s1[i]) j++;if(j==l2) printf("%d\n",i-l2+1),j=nxt[j];}for(int i=1;i<=l2;i++) printf("%d ",nxt[i]);return puts(""),0;
}

最小循环表示

工艺
\(O(n)\)求一个环从某点断开按一定方向形成的字典序最小的链

int i,j=2,k,l,p,s[610000];
int main()
{cin>>l;for(i=1;i<=l;i++) cin>>s[i],s[i+l]=s[i];for(i=1;j<=l&&i<=l&&k<=l;){if(s[i+k]==s[j+k]) {k++;continue;}s[i+k]<s[j+k]?j+=k+1:i+=k+1;if(i==j) i++;k=0;}for(;p<l;p++) cout<<s[min(i,j)+p]<<" ";
}

Mancher

【模板】manacher算法
求出以每个位置为中心的最长回文串,复杂度\(O(n)\),证明:每次操作要么不动\(while\),要么给两个单调的指针至少\(+1\)


const int N=3e7+10;
char s[N],t[N];
int l,p[N],R,C,Ans;
int main()
{scanf("%s",t+1);for(int i=1,len=strlen(t+1);i<=len;i++)s[++l]='#',s[++l]=t[i];s[++l]='#';for(int i=1;i<=l;i++){p[i]=i<=R?min(p[C*2-i],R-i):1;while(s[i+p[i]]==s[i-p[i]]&&i+p[i]<=l&&i-p[i]>=1) p[i]++;if(i+p[i]-1>R) R=i+p[i]-1,C=i;Ans=max(Ans,p[i]-1);}cout<<Ans<<endl;
}

AC自动机

【模板】AC自动机(加强版)
用于处理多串匹配单串等多串问题,复杂度\(O(n*26)\)
方式是先建\(Trie\),求出\(fail\)指针后建成\(Trie\)图

int n,node,fail[N],ch[N][26];
queue<int> Q;
void Insert(char *s,int id)
{int x=0,l=strlen(s+1);for(int i=1;i<=l;i++){int &p=ch[x][s[i]-'a'];if(!p) p=++node;x=p;}
}
void Get_fail()
{for(int i=0;i<26;i++) if(ch[0][i]) Q.push(ch[0][i]);while(!Q.empty()){int x=Q.front();Q.pop();for(int i=0;i<26;i++)if(ch[x][i]) fail[ch[x][i]]=ch[fail[x]][i],Q.push(ch[x][i]);else ch[x][i]=ch[fail[x]][i];}
}

后缀数组

【模板】后缀排序
用于处理字符串后缀的东西(不过这东西Noip不会考,省选题倒是经常出现)
复杂度\(O(nlogn)\),基于一种倍增和桶排的思想对后缀排序


const int N=1e6+10;
int m=300,t[N],x[N],y[N],rk[N],h[N],SA[N],l;char s[N];
int cmp(int i,int j,int k) {return y[i]==y[j]&&y[i+k]==y[j+k];}
void Sort()
{for(int i=1;i<=m;i++) t[i]=0;for(int i=1;i<=l;i++) t[x[i]]++;for(int i=1;i<=m;i++) t[i]+=t[i-1];for(int i=l;i>=1;i--) SA[t[x[y[i]]]--]=y[i];
}
void Get_SA()
{for(int i=1;i<=l;i++) x[i]=s[i],y[i]=i;Sort();for(int k=1,p=0;k<=l;k<<=1){for(int i=l-k+1;i<=l;i++) y[++p]=i;for(int i=1;i<=l;i++) if(SA[i]>k) y[++p]=SA[i]-k;Sort();swap(x,y);x[SA[1]]=p=1;for(int i=2;i<=l;i++) x[SA[i]]=cmp(SA[i],SA[i-1],k)?p:++p;if(p==l) break;m=p;p=0;}for(int i=1;i<=l;i++) rk[SA[i]]=i;for(int i=1,j=0;i<=l;i++){while(s[i+j]==s[SA[rk[i]-1]+j]) j++;h[rk[i]]=j;if(j) j--;}
}
int main()
{scanf("%s",s+1);l=strlen(s+1);Get_SA();for(int i=1;i<=l;i++) printf("%d ",SA[i]);
}

后缀自动机

【模板】后缀自动机
用于处理子串的问题。这家伙比SA好写复杂度还优秀适用范围还广些
不过Noip还是不会考,复杂度\(O(n)\)


const int N=2e6+10;
int l,lst=1,node=1,t[N],A[N],len[N],fa[N];
int ch[N][26],siz[N];char s[N];
void Extend(int c)
{int f=lst,p=++node;lst=p;len[p]=len[f]+1;siz[p]=1;while(f&&!ch[f][c]) ch[f][c]=p,f=fa[f];if(!f) {fa[p]=1;return;}int x=ch[f][c],y=++node;if(len[f]+1==len[x]) {fa[p]=x;node--;return;}len[y]=len[f]+1;fa[y]=fa[x];fa[x]=fa[p]=y;memcpy(ch[y],ch[x],sizeof(ch[y]));while(f&&ch[f][c]==x) ch[f][c]=y,f=fa[f];
}
int main()
{scanf("%s",s+1);l=strlen(s+1);for(int i=1;i<=l;i++) Extend(s[i]-'a');
}

转载于:https://www.cnblogs.com/xzyxzy/p/9903901.html

Noip前的大抱佛脚----字符串相关推荐

  1. Noip前的大抱佛脚----赛前任务

    赛前任务 tags:任务清单 前言 现在xzy太弱了,而且他最近越来越弱了,天天被爆踩,天天被爆踩 题单不会在作业部落发布,所以可(yi)能(ding)会不及时更新 省选前的练习莫名其妙地成为了Noi ...

  2. dmv io读写高的sql_适用于DBA的前8大新(或增强)SQL Server 2017 DMV和DMF

    dmv io读写高的sql Dynamic management views (DMVs) and dynamic management functions (DMFs) are system vie ...

  3. 台湾前十大科技公司拼不过三星(往后一点三星都不要买啦!)

    台湾前十大科技公司拼不过三星,往后一点三星都不要买啦!本来还可以买它的内存和液晶,不过现在是一点都不能买了,再买就真反了他了! 三星像糖果也像毒药,让台湾LED类股1年涨3倍,但也让鸿海市值一夜之间消 ...

  4. 【面试现场】如何在10亿数中找出前1000大的数

    小史是一个应届生,虽然学的是电子专业,但是自己业余时间看了很多互联网与编程方面的书,一心想进BAT互联网公司. 之前小史在BAT三家的面试中已经挂了两家,今天小史去了BAT中的最后一家面试了. 简单的 ...

  5. js 包含某个字符串_[译] 5 大 JavaScript 字符串操作库

    原文地址:5 String Manipulation Libraries for JavaScript 原文作者:Mahdhi Rezvi 译文出自:掘金翻译计划 本文永久链接:https://git ...

  6. 快速排序算法的实现 随机生成区间里的数 O(n)找第k小 O(nlogk)找前k大...

    思路:固定一个数,把这个数放到合法的位置,然后左边的数都是比它小,右边的数都是比它大 固定权值选的是第一个数,或者一个随机数 因为固定的是左端点,所以一开始需要在右端点开始,找一个小于权值的数,从左端 ...

  7. hdu1280 前m大的数(数组下标排序)

    前m大的数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

  8. 如何在10亿数中找出前1000大的数

    1.排序方法 首先能想到的就是先排序,然后取前1000个数,或者部分排序,只排出前1000个数就行 缺点:这些方法的时间复杂度都比较高 2,分治法 可以使用分治法,这有点类似快排中partition的 ...

  9. hdu 1280 前m大的数 哈希

    前m大的数 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Subm ...

最新文章

  1. 改进型 clock 页面置换算法实现_ID生成算法雪花算法介绍及实现
  2. linux gdb调试问题汇总
  3. Linux 服务器安装discuz 7.2论坛
  4. k8s 资源文件基础练习
  5. P4424-[HNOI/AHOI2018]寻宝游戏【结论】
  6. 中读取数据_Flink入门实战 (中)
  7. Linux手机研发要过五大难关
  8. 二叉搜索树的操作题集
  9. acp cp linux命令,系统运维
  10. Git更新本地分支信息
  11. 单片机IO详解(上拉 下拉 准双向 输入 输出 推挽 开漏)
  12. Exch:POP3 和 IMAP4 操作指南
  13. 日本流行语------收录
  14. Onetab快速删除所有历史网页
  15. sklearn.svm.SVC的方法decision_function_shape:ovr 或者 ovo
  16. Linux-Ubuntu终端命令
  17. android程序保活官方推荐
  18. zigbee知识介绍
  19. 你所不知道的粘接强度检测知识大全详解
  20. Swift Jama Matrix线性代数矩阵运算库

热门文章

  1. python学习笔记-Day17(jinja2)
  2. R710后台更新网卡驱动
  3. 使用VS2008开发及部署Excel AddIn 心得
  4. Vivado开发过程中生成的主要文件
  5. java soa例子_哪位大牛能举个实例讲下SOA与传统架构的区别?
  6. ipython中matplotlib无法显示图片Could not connect to any x display
  7. CMB标量功率谱第一个谱指数跑动项n(1)跑动带来的影响
  8. 牛客华为机试第1题python
  9. pyhton列表习题
  10. 使用 qrcodejs 生成二维码的几个问题