解题思路
这是一道字符串匹配问题,主要思路如下:
-
问题分析:
- 给定文本串text和模式串pattern
- 需要找到text中包含pattern所有字符的最短子串
- pattern中的字符在子串中可以不连续出现
- 输出最短子串的起止位置
-
解决方案:
- 使用双指针技术
- 外层循环遍历文本串
- 内层匹配模式串的每个字符
- 记录每次匹配成功的起止位置
- 更新最短匹配长度
-
实现细节:
- 使用变量记录当前匹配位置
- 维护全局最小长度和对应位置
- 处理多组输入的情况
代码
#include <iostream>
#include <string>
#include <climits>
using namespace std;
int main() {
string s, t;
while (cin >> s >> t) {
int n = s.size(), m = t.size();
int a = -1, b = -1; // 当前匹配的起止位置
int l = -1, r = -1; // 最终结果的起止位置
int min_len = INT_MAX;
for (int i = 0, j = 0; i < n; i++) {
if (s[i] == t[j]) {
if (j == 0) {
a = i; // 记录起始位置
}
j++;
}
if (j == m) { // 找到一个匹配
b = i;
j = 0; // 重置模式串指针
if (b - a < min_len) { // 更新最短匹配
min_len = b - a;
l = a;
r = b;
}
i = a; // 回退到起始位置继续查找
}
}
cout << l << " " << r << endl;
}
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String s = sc.next();
String t = sc.next();
int n = s.length(), m = t.length();
int a = -1, b = -1; // 当前匹配的起止位置
int l = -1, r = -1; // 最终结果的起止位置
int minLen = Integer.MAX_VALUE;
for (int i = 0, j = 0; i < n; i++) {
if (s.charAt(i) == t.charAt(j)) {
if (j == 0) {
a = i; // 记录起始位置
}
j++;
}
if (j == m) { // 找到一个匹配
b = i;
j = 0; // 重置模式串指针
if (b - a < minLen) { // 更新最短匹配
minLen = b - a;
l = a;
r = b;
}
i = a; // 回退到起始位置继续查找
}
}
System.out.println(l + " " + r);
}
sc.close();
}
}
def find_shortest_match(s: str, t: str) -> tuple:
n, m = len(s), len(t)
a = b = l = r = -1
min_len = float('inf')
i = j = 0
while i < n:
if s[i] == t[j]:
if j == 0:
a = i # 记录起始位置
j += 1
if j == m: # 找到一个匹配
b = i
j = 0 # 重置模式串指针
if b - a < min_len: # 更新最短匹配
min_len = b - a
l, r = a, b
i = a # 回退到起始位置继续查找
i += 1
return l, r
def main():
while True:
try:
s, t = input().split()
l, r = find_shortest_match(s, t)
print(f"{l} {r}")
except EOFError:
break
if __name__ == "__main__":
main()
算法及复杂度
- 算法:双指针扫描
- 时间复杂度:
- 最坏情况下需要回退重新匹配
- 空间复杂度:
- 只需要常数额外空间