最近看了下字符串匹配的问题,个人对于Sunday算法比较感兴趣,介绍一下自己对于它的想法。
切入正题。字符串S1和S2,(假定S1长度大于等于S2)要求在S1中包含S2即S1可以匹配S2。Sunny算法的基本思想如下:
首先给分别给S1和S2两个伪指针。
FKSJDKEJKSJEBC 即定义两个变量分别指向S1和S2的字符
i 串的某一字符位置(即代码中的i和j,初始都指向字符串的首位字符)。
FSJEB
j
然后进行匹配操作,即将i和j在S1和S2中分别同时移动,然后进行匹配看是否相等(如判断S1[i]与S2[j]是否相等)。之后判断的结果大致可以分为两种情况:
一、j移动到S2末端时没有出现S1[i]与S2[j]不匹配的情况。这种情况就比较好处理即S1中包含字符串S2。
FKSJDKEJKSJEBC
i
FKSJD
j
二、j在从头至尾移动过程中出现不匹配情况。当出现不匹配情况时记录一下,依旧将i移动到字符串S1的末尾。此时分为两种情况,判断S1[i + 1]字符是否存在于S2字符串中:(下面注意,移动S2的位置其实就是移动i的位置,因为j永远从S2的0开始对照S1[i]进行匹配)
①如果存在则将S2中的最靠后的匹配S1[i + 1]的字符(注意S2可能出现多个匹配的字符,此时要使用最靠后的那个字符)移动到对应S1的位置。
FKSJDEJKSJEBC FKSJDEJKSJEBC
i i+1 i
FEJEB 这里S1[i+1]是E,将E在S2中进行匹配。 FEJEB 这里注意不能将S2中的第一个E移动到匹配S1的位置。
j j
②不存在则将j(初始化为0)移动到i+1的位置,即将S2移动到S1的i+1的位置,再次进行以上匹配操作。
FKSJDSEJKSJEBC FKSJDSEJKSJEBC
i i+1 i
FEJEB 由此可以看出S1[i+1]=S不存在于S2中, FEJEB 将i移动到原先i+1的下一位
j 于是直接将S2移动到i+1的位置,即移动i j
具体代码如下:
bool match(string S1, string S2) {
int l1 = S1.length();
int l2 = S2.length();
int i = 0, j = 0; //两个指针分别代表指向S1和S2的位置
if (l1 < l2) return false; //判断S1和S2的长度是否对
while (i <= l1 - l2) {
int p = 0; //标示S2中是否存在与S1不符的字符
for (j = 0; j < l2; j++) {
if (S1[i] != S2[j]) p = 1; //不符合标注为1
i++;
}
if (p == 0) return true;
int q = -1; //标示与S1[i]匹配的位置
for (j = 0; j < l2; j++) {
if (S1[i] == S2[j]) q = j;
}
i = i - q; //移动i的位置(其实等同于移动S2的位置,因为j永远从S2的0为开始匹配)
}
return false;
}