上篇中谈到可以通过快速排序将字符串的包含问题的算法时间复杂度优化至O(nlogn)+O(mlogm)+O(m+n),那么还有没有更好的算法时间复杂度呢?可以采用计数排序的方法,排序的时间复杂度为O(m+n),线性扫描的时间复杂度为O(m+n)。故总的时间复杂度为:O(m+n)+O(m+n)=O(m+n)。但是此时的空间复杂度为:O(m+n)。
对于上述思路,编写代码如下:
#include"stdafx.h"
#include<stdio.h>
#include"string"
#include"iostream"
using namespace std;
void count_sort(string str,string &help_str)
{
//定义辅助数组,记录每一个字符的个数
int help[26]={0};
//轮询字符串,得到每一个字符出现的次数
for(int i=0;i<str.length();i++)
{
int index=str[i]-'A';
help[index]++;
}
//得到每个字符应该出现的位置
for(int j=1;j<26;j++)
{
help[j]+=help[j-1];
}
//将字符填充到自己的位置
for(int i=0;i<str.length();i++)
{
int index=str[i]-'A';
int pos=help[index]-1;
help_str[pos]=str[i];
help[index]--;
}
}
void compare(string &s1,string &s2)
{
int pos_short=0;
int pos_long=0;
//同时轮询两个排序好的字符串
while(pos_short<s2.length()&&pos_long<s1.length())
{
//如果长字符串的字符值小于段字符串的字符值,pos_long++
while(s1[pos_long]<s2[pos_short]&&pos_long<s1.length())
{
pos_long++;
}
//如果s2中出现重复的字符
while(s2[pos_short]==s2[pos_short+1])
pos_short++;
//如果出现s1[]>s2[]的情况,break;
if(s1[pos_long]!=s2[pos_short])
break;
pos_long++;
pos_short++;
}
//判断是否是break跳出,如果是,就没有pos_short==s2.length()
if(pos_short==s2.length())
cout<<"true"<<endl;
else
cout<<"false"<<endl;
}
int main()
{
string s1="ADEFGHAB";
string s2="AED";
string help_s1=s1;
string help_s2=s2;
cout<<s1<<endl;
cout<<s2<<endl;
count_sort(s1,help_s1);
count_sort(s2,help_s2);
cout<<help_s1<<endl;
cout<<help_s2<<endl;
compare(help_s1,help_s2);
return 0;
}
总结:这种的方法和上一篇的唯一的区别在于排序方法的不同。有点用空间换时间的感觉。