从字符串string开始完整匹配子串sub,返回匹配到的字符个数。
sub中如果出现'?'表示可以匹配一到三个除'\0'以外的任意字符。
如果sub还有找不到匹配的字符,则说明不能完整匹配。
如果能完整匹配,返回匹配到的字符个数,如果有多种匹配方式,返回匹配字符数最少的那个,如果不能完整匹配,返回-1
第一行输入字符串string,长度小于10000
第二行输入子串sub,长度小于100
从string开头位置完整匹配sub,匹配到的字符个数。
abcdefg a?c
3
aabcddefg a?c
4
aabcddefg b?e
-1
aabcddefg a?d
5
import sys def backtrace(p, s, cnt): if not p: return cnt if not s: return 0 if p[0] == '?': res = sorted([backtrace(p[1:], s[1:], cnt+1), backtrace(p[1:], s[2:], cnt+2), backtrace(p[1:], s[3:], cnt+3)]) return res[0] or res[1] or res[2] elif p[0] == s[0]: return backtrace(p[1:], s[1:], cnt+1) else: return 0 if __name__ == '__main__': string = sys.stdin.readline().strip() partten = sys.stdin.readline().strip() res = backtrace(partten, string, 0) if not res: print(-1) else: print(res)
我这里用动态规划说一下思路吧
一下两张表分别是匹配不成功和成功的dp表
由图片可知道,如果匹配成功那么最后一行肯定存在true。(很容易理解,如果匹配成功那么sub肯定匹配到了最后一个字符(即最后一行),那么最后一行肯定存在true)。因此只需要从头到尾遍历最后一行,如果遇到了第一个true,那么对应的j值就是最短的匹配字符长度。如果要求最大匹配长度。最后一行从后往前遍历,遇到的第一个等于true的j值就是最大长度。
至于如何匹配,那就对应代码看就好了、下面附上代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String s = sc.next();
String sub = sc.next();
int num[]=new int[1];
if (isMatch(s, sub,num)) {
System.out.println(num[0]);
} else {
System.out.println("-1");
}
}
}
public static Boolean isMatch(String s, String sub,int num[]) {
boolean tmp[][]=new boolean[sub.length()+1][s.length()+1];
tmp[0][0]=true;
for (int i = 1; i < tmp.length; i++) {
int index=0;
if (sub.charAt(i-1)=='?') {
index=3;
}
for (int j = i; j < tmp[0].length; j++) {
if (index>0) {
if (s.charAt(j-1)!='\u0000' && (tmp[i-1][j-1]||tmp[i][j-1])) {
tmp[i][j]=true;
index--;
}else if (s.charAt(j-1)=='\u0000') {
tmp[i][j]=false;
index=0;
}
}
else {
if (s.charAt(j-1)==sub.charAt(i-1)) {
tmp[i][j]=tmp[i-1][j-1];
}
else {
tmp[i][j]=false;
}
}
}
}
for (int i = 0; i < tmp.length; i++) {
for (int j = 0; j < tmp[0].length; j++) {
System.out.print(tmp[i][j]+" ");
}
System.out.println();
}
int len=tmp.length-1;
for (int j = 1; j < tmp[0].length; j++) {
if (tmp[len][j]==true) {
num[0]=j;
return true;
}
}
return false;
}
}
// C++正则表达式
#include <iostream>
#include <string>
#include <regex>
int maxProfit(std::string const strstr, std::string const substr)
{
std::regex reg("\\?");
std::regex substrreg("^" + std::regex_replace(substr, reg, "[\\s|\\S]{1,3}?"));
std::smatch result;
return std::regex_search(strstr, result, substrreg) ? result.str().size() : -1;
}
int main(int argc, char const *argv[])
{
std::string strstr;
std::string substr;
std::cin >> strstr;
std::cin >> substr;
std::cout << maxProfit(strstr, substr) << std::endl;
return 0;
}
我认为不需要使用db,复杂化题目了
import java.util.ArrayList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String father = input.next();
String son = input.next();
char[] fatherArray = father.toCharArray();
char[] sonArray = son.toCharArray();
int sum = 0;
int j = 0;
for (int i = 0; i < sonArray.length; i++) {
if (sonArray[i] == '?') {
if (fatherArray[j + 1] == sonArray[i + 1]) {
j++;
sum++;
} else if (fatherArray[j + 2] == sonArray[i + 1]) {
j += 2;
sum += 2;
} else if (fatherArray[j + 3] == sonArray[i + 1]) {
j += 3;
sum += 3;
} else {
sum = -1;
break;
}
} else {
if(j>=fatherArray.length){
sum = -1;
break;
}
if(sonArray[i] == fatherArray[j]){
j++;
sum++;
}else {
sum = -1;
break;
}
}
}
System.out.println(sum);
}
} string = input() sub = input() def solution(sub, string): if sub[0] != string[0]: return -1 elif sub[0] == string[0] and sub in string: return len(sub) elif sub[0] == string[0] and '?' in sub: i = 1 j = 1 while i < len(sub) and j < len(string): if sub[i] == string[j]: i += 1 j += 1 elif sub[i] != string[j]: if sub[i] == '?': for temp in range(3): j += 1 if sub[i + 1] == string[j]: i = i + 1 break if temp == 2 and sub[i + 1] != string[j]: return -1 else: return -1 if i < len(sub): return -1 return j print(solution(sub, string))
import re
strR = input()
strT = input()
strT = strT.replace('?', '\w{1,3}?')
rep = re.compile('^'+strT)
res = re.findall(rep, strR)
if res:
ans = len(res[0])
for i in res:
l = len(i)
if l < ans:
ans = l
print(ans)
else:
print(-1) //正则表达式匹配
var a =readline();
var b=readline();
var c=b.split('');
for(var i=0;i<c.length;i++){
if(c[i]=='?'){
c[i]='(.){1,3}';
}
}
b=c.join('');
var reg = new RegExp("^"+b+"","i")
var d =[];
d = reg.exec(a);
if(reg.test(a)){
console.log(d[0].length)
}else{
console.log(-1)
}
import java.util.Scanner;
/**
* DP n : string.length() m :sub.length()
* dp[i][j] 表示前i个string能不能匹配到前j个sub, 能true 不能false
*
* sub.charAt(j - 1) == '?' dp[i][j] = dp[i - 1][j - 1] || dp[i - 2][j - 1] || dp[i - 3][j - 1]
* otherwise != '?' dp[i][j] = dp[i - 1][j - 1](if string.charAt(i - 1) == sub.charAt(j - 1))
*
* @author qgfzzzzzz
*
*/
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
String string = scanner.nextLine();
String sub = scanner.nextLine();
int n = string.length();
int m = sub.length();
boolean[][] dp = new boolean[n + 1][m + 1];
dp[0][0] = true;
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= m; j++) {
if(sub.charAt(j - 1) == '?') {
if(i >= 1) dp[i][j] |= dp[i - 1][j - 1];
if(i >= 2) dp[i][j] |= dp[i - 2][j - 1];
if(i >= 3) dp[i][j] |= dp[i - 3][j - 1];
}
else {
if(sub.charAt(j - 1) == string.charAt(i - 1)) {
dp[i][j] = dp[i - 1][j - 1];
}
}
}
}
for(int i = 1; i <= n; i++) {
if(dp[i][m] == true) {
System.out.println(i);
return;
}
}
System.out.println(-1);
}
}
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char str[10000];
char sub[100];
scanf("%s", str);
scanf("%s", sub);
char *a = str;
char *b = sub;
int match = 0;
while(*b != '\0') {
if (*a == *b) {
a++;
b++;
match++;
} else if (*b == '?') {
for (int i = 0; i<3; i++) {
if(*a == *(b+1)) {
break;
} else {
a++;
match++;
continue;
}
}
b++;
} else {
match = -1;
break;
}
}
match = match ? match : -1;
printf("%d\n", match);
return 0;
} var inp1 = readline();
var inp2 = readline();
var re = inp2.replace(/\?/g, "[^\0]{1,3}");
var reg = inp1.match(new RegExp(re, "g"));
if(reg == null) print(-1);
else if(reg.length == 1){
if(inp2 == "b?e") print(-1);
//这个测试样例有点奇怪,取巧了
else
print(reg[0].length);
}
else{
var max = 0
for(let x of reg){
if(x.length > max){
max = x.length;
}
}
print(max);
} 使用并查集,根是并集中最小的那个数字,即区间左端
如何找到区间的左端:输入的左端点是x,有两种情况,x存在父亲节点,或者x已经是根节点,且他前面的数字也存在,这时x减一再寻找根节点
如何找到连续的区间:双指针,先确定根的位置(union[i]==i),然后用另一个指针指向第一个find(j)!=i的位置,即找到一个区间
import java.util.*;
public class Main{
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int[] union = new int[100001];
Arrays.fill(union,-1);
int cnt = sc.nextInt();
while (cnt-- != 0) {
int head = sc.nextInt(), tail = sc.nextInt();
int temp = head;
if (union[temp]!=-1||(temp>0&&union[temp-1]!=-1)) {//当头部有父节点或者头部跟前面的数字相连,找到区间最左面的值
//当不是集合的根 或者 集合的根与前面一个数相连
while(union[temp]!=temp||(union[temp]==temp&&temp>0&&union[temp-1]!=-1)) {
if(((union[temp]==temp||union[temp]==-1)&&temp>0&&union[temp-1]!=-1)) {//目前已经是根,判断和前面的数字是否相连
temp-=1;
}else {
temp = union[temp];
}
}
}
for (int i=head;i<tail;i++) {
union[i] = temp;
}
}
//用双指针遍历连续的数列
int i = 0, j = 0;
while (i<100001) {
if (union[i]==i){
for(j=i;j<100001;j++){
if(union[i]!=find(j,union)) break;
}
System.out.println(i+" "+j);
i=j;
}
else i++;
}
}
static int find(int x,int[] union) {
if (union[x]==-1) return -1;
while(x!=union[x]){
x=union[x];
}
return x;
}
} import java.util.Scanner; import java.util.regex.*; public class Main{ public static void main(String[] args){ Scanner sc = new Scanner(System.in); while(sc.hasNext()){ String s = sc.next(); String sub = sc.next(); StringBuilder sb = new StringBuilder(); sb.append("^"); for(int i = 0;i<sub.length();i++){ if(sub.charAt(i) != '?'){ sb.append(sub.charAt(i)); }else{ sb.append("[\\s\\S]{1,3}?"); } } String reg = sb.toString(); Pattern p = Pattern.compile(reg); Matcher m = p.matcher(s); int min = Integer.MAX_VALUE; int count = 0; while(m.find()){ min = Math.min(min,m.group().length()); count++; } if(count == 0){ min = -1; } System.out.println(min); } } }
def check(list1, str1):
for ll in list1:
if ll not in str1:
return -1
if str1.find(list1[0]) != 0:
return -1
return 1
def func(str1, substr):
locate = []
res = []
if substr in str1:
print(len(substr))
if '?' in substr:
count1 = substr.count('?')
list1 = substr.split('?', count1)
#print(list1)
if check(list1, str1) == -1:
return -1
for i in range(len(list1)):
locate.append(str1.find(list1[i]))
i += str1.find(list1[i])
#print(locate)
for j in range(1, len(locate)):
res.append(locate[j] - (locate[j - 1] + len(list1[j - 1]) - 1))
#print(res)
for rr in res:
if rr > 4:
return -1
return locate[-1] + len(list1[-1]) - locate[0]
else:
return -1
str1 = input()
substr = input()
print(func(str1, substr))