最小表示法
来源:互联网 发布:linux 文件夹删除 编辑:程序博客网 时间:2024/06/06 02:27
最小表示法与kmp算法一样都可以解决字符串匹配问题,但效率更高,代码短,作用更大。
最小表示法就是一个字符串的最小字典序。
怎么求一个字符串的最小字典序呢?
首先将这个字符串扩展一倍(建设存在d[]数组里),然后我们用三个指针i=0,j=1,k=0,来寻找最小字典序的开头字母,为了优于kmp,我们要做到O(n)。
i表示假设最小字典序为d[i];
j为辅助变量,用于证明i是不是最小字典序的开头;
k表示当以i开头和与j开头的字符串从第一个字母开始重复的部分的个数。
每次让k=0,若d[i+k]==d[j+k]就k++;(直到不满足条件再做下面的步骤)
若d[i+k]>d[j+k]则i=i+k+1;否则j=j+k+1;(想想为什么?)当i与j相等时,j++;
当i,j,k中有一个的长度大于原长度时则退出,答案即为min(i,j)。
总复杂度为o(n)。
poj1509:
给n个字符串输出每个字符串的最小字典序的开头字母在原字符串中的位置。
#include <stdio.h>#include <math.h>#include <string.h>#define INF 200005#define rep(i,l,r) for(i=l;i<=r;i++)int n,m,t;char a[INF];char b[INF];char c[INF],d[INF];int l=0,l1=0;int init(){ int i,j,k,p,step=0; scanf("%d",&t); while(t>0) { //memset(a,'0',sizeof(a)); l=0;k=0; scanf("%s",&a); l=strlen(a); //rep(i,0,l-1) // a[i+l]=a[i]; k=work(); printf("%d\n",k+1); t--; } return 0;}int min0(int a,int b){ if(a>=b)return b; else return a;}int work(){ int i=0,j=1,k=0,o; while(i<l && j<l && k<l ){ k=0; while(k<l && a[(i+k)%l]==a[(j+k)%l])k++; if(a[(i+k)%l]>a[(j+k)%l])i=i+k+1; else if(a[(i+k)%l]<a[(j+k)%l])j=j+k+1; if(i==j)j++; } if(i>j)i=j; return i;}int main(){ init(); return 0;}
还有一题,给你两个字符串,判断它们的最小字典序是否相等。(数据自己出吧。。。QAQ)
#include <stdio.h>#include <math.h>#include <string.h>#define INF 20000005#define rep(i,l,r) for(i=l;i<=r;i++)int n,m;char a[INF];char b[INF];char c[INF],d[INF];int l=0,l1=0;int init(){ int i,j,k,p,step=0; scanf("%s",&a); scanf("%s",&b);l1=strlen(b); l=strlen(a); //rep(i,0,l-1) // a[i+l]=a[i]; k=work(); //rep(i,0,l1-1) // b[i+l1]=b[i]; p=work2(); j=p; rep(i,k,l+k-1) { if(a[i%l]!=b[j%l]){step=1;break;} j++; } if (step)printf("No\n"); else{ printf("Yes\n"); printf("%s",d); } printf("\n"); return 0;}int min0(int a,int b){ if(a>=b)return b; else return a;}int work2(){ int i=0,j=1,k=0,o; while(i<l1 && j<l1 && k<l1 ){ k=0; while(k<l1 && b[(i+k)%l1]==b[(j+k)%l1])k++; if(b[(i+k)%l1]>b[(j+k)%l1])i=i+k+1; else if(b[(i+k)%l1]<b[(j+k)%l1])j=j+k+1; if(i==j)j++; } if(i>j)i=j; rep(o,0,l-1) c[o]=b[(i+o)%l]; return i; }int work(){ int i=0,j=1,k=0,o; while(i<l && j<l && k<l ){ k=0; while(k<l && a[(i+k)%l]==a[(j+k)%l])k++; if(a[(i+k)%l]>a[(j+k)%l])i=i+k+1; else if(a[(i+k)%l]<a[(j+k)%l])j=j+k+1; if(i==j)j++; } if(i>j)i=j; rep(o,0,l-1) d[o]=a[(i+o)%l]; return i;}int main(){ freopen("min.in","r",stdin); freopen("min.out","w",stdout); init(); //work(); fclose(stdin); fclose(stdout); return 0;}
最后吐糟一句,其实最小表示法在很多地方都很有用。。。(下次再补上来,sorry)
0 0
- 最小表示法
- poj1509(最小表示法)
- hdu4162(最小表示法)
- 最小表示法
- 最小表示法
- 最小表示法
- 最小表示法模板
- 最小表示法
- 最小表示法+uva719
- 最小表示法
- 最小表示法
- poj1509最小表示法
- 字符串最小表示法
- poj1509 最小表示法
- 最小表示法
- poj1509 最小表示法
- 【模版】最小表示法
- 最小表示法
- TVS学习
- uva 714 Copying Books (二分)
- JSP内置对象_1
- 游戏人物跟随鼠标移动的实现
- Android基础笔记(五)-网络编程
- 最小表示法
- java基础巩固之IO(三)
- 找球号(一)
- 【Plan 第五场】
- 好吧,十年之后
- OpenCv_背景差分结合LK金字塔进行运动物体跟踪
- 用Matlab绘制精美、高级图表的技术网站
- ios8指纹识别
- 【工作实例】cookie设置精确到毫秒案例