注:
正确性有待考察,因为没有题试试水
转载:
https://blog.csdn.net/superhackerzhang/article/details/6432559
算法说明:
令模式串为p={p[0],p[1],...,p[m-1]},长度为m。文本串为T={T[0],T[1],...,T[n-1]},长度为n.要求n>=m.
令k为p在T上的对齐位置,即p[0]与T[k],p[1]与T[k+1],.....,p[m-1]与T[k+m-1]相对应,检测在位置k是否匹配时只要逐个检查以上相对应的字符即可。当在某个位置发生失配时,根据T[k+m]来决定模式串向右移动的位置,因为一旦发生失配,模式串至少向右移动一位,因此T[k+m]必然要和模式串中相同字符的最右端出现相对应,否则会发生另一次失配。如果模式串中无T[k+m]字符,则将模式串向右移动m+1个位置。而在检查P与T的字符是否匹配时可以使用任意的顺序,而不必从左至右或从右至左,这是与KMP或BM最大的区别。
以下代码计算模式串的出现过的字母所在的位置,即p[m-1]的字母位置记为1,p[m-2]记为2,如果一个字母在模式串中出现多次,则记录最右边的出现位置。
map<char,int>pos;
void pre(string p,map<char,int>&pos)
{
for(int i=p.size()-1; i>=0; i--)
{
if(pos.find(p[i])==pos.end())
pos.insert(pair<char,int>(p[i],p.size()-i));
}
}
Quick Search 主体函数 —— 连续输出模板串在文本里的位置
void QS(string p,string text,map<char,int>pos)
{
int k=0,m=p.size(),l=text.size();
bool flag=false;
while(k+m<=l)
{
int j=0;
for(; j<m; j++)
{
if(p[j]!=text[j+k])
{
if(k+m>=l)
{
if(!flag)
cout<<0;
return;
}
if(pos.find(text[k+m])!=pos.end())
k+=pos[text[k+m]];
else
k=k+m+1; //失配后模板串至少向右移动一位
break;
}
}
if(j==m) //输出模板串出现在文本里的位置
{
cout<<k+1<<" ";
flag=true;
k++;
}
}
if(!flag)
cout<<0;
return;
}