这里我们介绍两种字符串匹配的方式,第一种超级简单,第二种比第一种稍微复杂些。
主串 S : abcabcdabc 模式串(子串)T : abcd
求:模式串 t 在主串 s 中的位置
第一种解法
i 0
S | a | b | c | a | b | c | d | a | b | c |
T | a | b | c | d |
j 0
i 对应s,j对应T
(1)i = 0 : 比较 S[0], S[1], S[2], S[3] 和 T[0], T[1], T[2], T[3]的关系
(2)i = 1 : 比较 S[1], S[2], S[3], S[4] 和 T[0], T[1], T[2], T[3]的关系
(3)i = 2 : 比较 S[2], S[3], S[4], S[5] 和 T[0], T[1], T[2], T[3]的关系
。。。。。。
综上所述:当 i 固定时,j 的范围是 0 ~ 3,我们只需比较 S[i + j] 和 T[ j ]的关系即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main(){
string s, t;
cin >> s >> t;
int len1 = s.size();
int len2 = t.size();
/* i = 0: s[0] s[1] s[2] s[3]
t[0] t[1] t[2] t[3]
i = 1: s[1] s[2] s[3] s[4]
t[0] t[1] t[2] t[3]
*/
for(int i = 0; i < len1; i++){
for(int j = 0; j < len2; j++){
if(s[i+j] != t[j]){
break;
}
if(j == len2 - 1){
cout << i << endl;
}
}
}
return 0;
}
第二种解法
第一种解法我们用的是两个for循环,这次我们使用while循环。
先上代码:
#include <bits/stdc++.h>
using namespace std;
int main(){
string s, t;
cin >> s >> t;
int len1 = s.size();
int len2 = t.size();
int i = 0, j = 0;
while(i < len1 && j < len2){
if(s[i] == t[j]){
i++;
j++;
}else{
i = i - j + 1;
j = 0;
}
}
if(j == len2){
cout << i - len2 << endl;
}
return 0;
}
设 i = 0, j = 0,当 i < s.size() 且 j < t.size()时不断循环,当s [ i ] == t[ j ]时,i ++, j++, 否则 i 回到一位置,j 变为0.
这段代码的核心就是找到 i 的返回值,从代码中可以得知 i = i - j + 1
大家可以记住这个规律,在草稿纸上可以进行验证是不是 i = i - j + 1
if(j == len2){
cout << i - len2 << endl;
}
对于这段代码,为什么输出的是 i - len2,我们知道当 j 匹配完全时,j 肯定等于T.size() - 1
以主串 S : abcabcdabc 模式串(子串)T : abcd为例,当 i = 6, j = 3时,匹配成功,这时s[i] == t [ j ], i++, j++。 则 i = 7, j = 4, 不满足循环的条件,退出循环,这时 j == t.size(), 此时输出其位置,即 i - len2。(刚开始我以为 i 为 6,所以结果为 i - len2 + 1,但 实际上 j == 4 的时候,i 也进行了 加操作,所以结果为 i - len2)。