字符串各算法学习
2015-09-27 16:03
363 查看
在网络赛期间罢赛不做题了过来写博客真是一种罪过,然而被零封实在是没有勇气坚持最后一个小时。。。。
两个队友都不在,单挑太水了
————————————————————————————————————————————————————————
进入正题
求该串中连续m个长为l的子串互不重复的数目
HDOJ 2222
习题链接:我bin带你飞——AC自动机专题
第一题HDOJ2222模板题
第二题HDOJ2896需要改动模板:对end数组中记录各个字符串的编号
第三题HDOJ3065需要改动模板:每个字符串在模式串之中匹配了几次(在query中添加一个标记数组)
第四题ZOJ3430需要添加一个base64的解码算法。。。弱写了太久,还是WA,直接搬运我bin的吧:
两个队友都不在,单挑太水了
————————————————————————————————————————————————————————
进入正题
字符串常用算法
Part 1:字符Hash
模版上述地方有,根据题目对自己的理解进行解释:HDOJ 4821
题意:给定m和l和一个字符串,求该串中连续m个长为l的子串互不重复的数目
char s[maxn]; ull base[maxn],Hash[maxn]; map<ull,int> mp; int main(){ //input; int m,l,i,len,ans; base[0]=1; for(i=1;i<maxn;i++) base[i]=base[i-1]*seed; while(scanf("%d%d",&m,&l)!=EOF){ scanf("%s",s); ans=0; len=strlen(s); Hash[len]=0; for(i=len-1;i>=0;i--) Hash[i]=Hash[i+1]*seed+s[i]-'a'; for(i=0;i<l&&i+m*l<len;i++){//枚举以i位置为起点,长度为m*l的子串是否合法 mp.clear(); for(int j=i;j<i+m*l;j+=l){// ull temp=Hash[j]-Hash[j+l]*base[l]; mp[temp]++; } if (mp.size()==m) ans++; for(int j=i+m*l;j+l<=len;j+=l){//更换起点,i+km为起点依次往后推 ull temp=Hash[j-m*l]-Hash[j-(m-1)*l]*base[l]; mp[temp]--; if (!mp[temp]) mp.erase(temp); temp=Hash[j]-Hash[j+l]*base[l]; mp[temp]++; if (mp.size()==m) ans++; } } printf("%d\n",ans); } return 0; }
HDOJ 4080
/* 字符串题目注意: Hash,Rank这类单词一定首字母大写,不然CE 题意:给定一个字符串和出现次数k, 找出至少出现k次的最长的子串长度以及其最后一次出现的位置(首字符的位置) 二分判断某个长度是否可行,找到最大的。。。。 按照哈希值的大小排序:越大的位数“相对” 越长 */ int l,len,pos,Rank[maxn]; ull Hash[maxn],xp[maxn],haha[maxn]; char str[maxn]; bool cmp(int a,int b){ /*if (haha[a]==haha) return a<b; return haha[a]<haha[b];*/ return (haha[a]!=haha[b])?(haha[a]<haha[b]):(a<b); } bool solve(int mid){ int c=1; pos=-1; for(int i=0;i<len-mid+1;i++){ Rank[i]=i; haha[i]=Hash[i]-Hash[i+mid]*xp[mid]; } sort(Rank,Rank+len-mid+1,cmp); //注意第二个参数,len-mid+1描述的是数组中元素个数 //开始找 for(int i=0;i<len-mid+1;i++){ if (i==0||haha[Rank[i]]!=haha[Rank[i-1]]) c=1; else{ c++; if (c>=l) pos=max(pos,Rank[i]); } } return pos>=0; } int main(){ //input; while(scanf("%d",&l)!=EOF){ if (!l) break; scanf("%s",str); len=strlen(str); if (l==1){//特判,串长为1 printf("%d %d\n",len,0); continue; } memset(Hash,0,sizeof(Hash)); memset(xp,0,sizeof(xp)); xp[0]=1; for(int i=len-1;i>=0;i--) Hash[i]=Hash[i+1]*x+str[i]-'a'; for(int i=1;i<len;i++) xp[i]=xp[i-1]*x; if (!solve(1)){//又是细节判断,无解输出 puts("none"); continue; } int low=1,high=len,mid; while(low+1<high){ mid=(low+high)>>1; if (solve(mid)) low=mid; else high=mid; } solve(low); printf("%d %d\n",low,pos); } return 0; }
Trie(字典树)原理
POJ3630
POJ3630题解
[b]KMP算法
我bin带你飞的专题直接刷爆把:练习KMPAC自动机(听妈妈说学过这个算法就一定AK)
看过算法之后,学学我bin神的模板保证比赛平安:HDOJ 2222
struct Trie{ int next[500010][26],fail[500010],end[500010]; int root,L; int newnode(){ for(int i=0;i<26;i++) next[L][i]=-1; end[L++]=0; return L-1; } void init(){ L=0; root=newnode(); } void insert(char buf[]){ int len=strlen(buf); int now=root; for(int i=0;i<len;i++){ if (next[now][buf[i]-'a']==-1) next[now][buf[i]-'a']=newnode(); now=next[now][buf[i]-'a']; } end[now]++; } void build(){ queue<int> Q; fail[root]=root; for(int i=0;i<26;i++) if (next[root][i]==-1) next[root][i]=root; else{ fail[next[root][i]]=root; Q.push(next[root][i]); } while(!Q.empty()){ int now=Q.front(); Q.pop(); for(int i=0;i<26;i++) if (next[now][i]==-1) next[now][i]=next[fail[now]][i]; else{ fail[next[now][i]]=next[fail[now]][i]; Q.push(next[now][i]); } } } int query(char buf[]){ int len=strlen(buf); int now=root; int res=0; for(int i=0;i<len;i++){ now=next[now][buf[i]-'a']; int temp=now; while(temp!=root){ res+=end[temp]; end[temp]=0; temp=fail[temp]; } } return res; } }; char buf[1000010]; Trie ac; int main(){ //input; int T,n; scanf("%d",&T); while(T--){ scanf("%d",&n); ac.init(); for(int i=0;i<n;i++){ scanf("%s",buf); ac.insert(buf); } ac.build(); scanf("%s",buf); printf("%d\n",ac.query(buf)); } return 0; }
习题链接:我bin带你飞——AC自动机专题
第一题HDOJ2222模板题
第二题HDOJ2896需要改动模板:对end数组中记录各个字符串的编号
第三题HDOJ3065需要改动模板:每个字符串在模式串之中匹配了几次(在query中添加一个标记数组)
第四题ZOJ3430需要添加一个base64的解码算法。。。弱写了太久,还是WA,直接搬运我bin的吧:
unsigned char buf[2050]; int tot; char str[4000]; unsigned char s[4000]; unsigned char Get(char ch) { if( ch>='A'&&ch<='Z' )return ch-'A'; if( ch>='a'&&ch<='z' )return ch-'a'+26; if( ch>='0'&&ch<='9' )return ch-'0'+52; if( ch=='+' )return 62; else return 63; } void change(unsigned char str[],int len) { int t=0; for(int i=0;i<len;i+=4) { buf[t++]=((str[i]<<2)|(str[i+1]>>4)); if(i+2 < len) buf[t++]=( (str[i+1]<<4)|(str[i+2]>>2) ); if(i+3 < len) buf[t++]= ( (str[i+2]<<6)|str[i+3] ); } tot=t; } main(): int n,m; while(scanf("%d",&n) == 1) { ac.init(); for(int i = 0;i < n;i++) { scanf("%s",str); int len = strlen(str); while(str[len-1]=='=')len--; for(int j = 0;j < len;j++) { s[j] = Get(str[j]); } change(s,len); ac.insert(buf,tot,i); }
相关文章推荐
- C2第二次作业
- Java学习笔记【集合】
- ARP欺骗与中间人攻击
- 黑马程序员-day06-面向对象
- Scala深入浅出进阶经典 第69讲:Scala并发编程react、loop代码实战详解
- Javascript中的依赖注入
- php类和命名空间介绍,成员方法和类方法,类的继承与方法重写
- 编译安装php, Cannot find libmysqlclient under /usr
- linux下C语言开发入门
- 【转载,必须】可变长参数列表误区与陷阱——va_end是必须的吗?
- Scala深入浅出进阶经典 第68讲:Scala并发编程原生线程Actor、Cass Class下的消息传递和偏函数实战解析及其在Spark中的应用源码解析
- Runtime类中的freeMemory,totalMemory,maxMemory等几个方法
- 深入InnoDB的MVCC机制
- 【POI2011】【BZOJ2527】Meteors
- 【排序算法】——堆排序
- itms-services协议,不通过AppStore,直接安装IOS应用程序
- linux shell
- getText()和getText().toString()
- Scala深入浅出进阶经典第67讲:Scala并发编程匿名Actor、消息传递、偏函数实战解析及其在Spark源码中的应用解析
- Java并发编程实践之Callable,Future,RutureTask的使用