字符串的一些算法

来源:互联网 发布:java telnet 编辑:程序博客网 时间:2024/05/22 05:01


一、编辑距离(求字符串相似度)


int lowofthree(int i,int j,int k){int m=(i<j)?i:j;int n=(m<k)?m:k;return n;}int dis(char *str1,int m,char *str2,int n){int dist[m+1][n+1];for(int i=0;i<=m;++i)dist[i][0]=i;for(int i=0;i<=n;++i)dist[0][i]=i;for(int i=1;i<=m;++i)for(int j=1;j<=n;++j){int temp=(str1[i-1]==str2[j-1])?0:1;dist[i][j]=lowofthree(dist[i-1][j]+1,dist[i][j-1]+1,dist[i-1][j-1]+temp);}return dist[m][n];}int main() {    char str1[10]="cafe";    char str2[10]="coffee";    int m=strlen(str1);    int n=strlen(str2);    cout<<dis(str1,m,str2,n)<<endl;}

二、kmp算法

自己花半天时间写的代码,逻辑混乱,用了多重循环,边界检查调试诸多bug,完了在hihocode通过。编码方式影响了性能及可读性。代码如下:

#include <string.h>#include <stdlib.h>#include <iostream>using namespace std;void kmpnext(char * str,int * next){int len=strlen(str);for(int i=0;i<len;++i)next[i]=-1;for(int i=1;i<len;++i){int j=i-1;while(j>=0){if(str[i]==str[next[j]+1]){next[i]=next[j]+1;break;}elsej=next[j];}}}int kmpmatch(char * str1, char * str2,int * next){int p=0,q=0,count=0;int len1=strlen(str1);int len2=strlen(str2);while(p<=len1){while(str1[p]==str2[q]&&q<len2)p++,q++;if(q==0)p++;else if(q==len2)count++,q=next[q-1]+1;elseq=next[q-1]+1;}return count;}int main(){int a;cin>>a;char str1[10001];char str2[1000001];int next[10000];for(int i=0;i<a;i++){cin>>str1;cin>>str2;kmpnext(str1,next);int count=kmpmatch(str2,str1,next);cout<<count<<endl;}return 0;}


拜读了大神的代码,又简洁,性能又好。我的执行时间是210ms,大神代码的时间是46ms。代码如下:

#include <iostream>#include <cstring>#include <cstdio>using namespace std;int main(){    char t[10050],s[1000007];    int c;scanf("%d",&c);    while(c--)    {        scanf("%s%s",t,s);        int flink[10004]={};        int i=0,j=-1;        flink[0]=-1;        int len=strlen(t);        while(i<len)        {            if(j==-1 || t[i]==t[j])                flink[++i]=++j;            else                j=flink[j];        }        int ans=0;        i=j=0;        int n=len;        len=strlen(s);        while(i<len)        {            if(j==-1 || s[i]==t[j])            {                ++i;++j;            }            else            {                j=flink[j];            }            if(j==n) ans++;        }        printf("%d\n",ans);    }    return 0;}

大神的flink表示当前需要匹配的字符映射表,并计算了在模式为\0时的映射量,巧妙减少边界条件的检查。我的next是上一个字符匹配好的字符映射表。

0 0