写在前面的话:题目稍有变化,注意审题!
题目:
给定字符串target和source,判断target是否为source的子序列。你可以认为target和source 中仅包含英文小写字母,字符串source可能会很长,长度~=500,000,而target是个短字符串,长度<=100。字符串的一个子序列是原始字符串删除一些(也可以不删除)字符而不改变剩余字符相对位置形成的新字符串,例如,'abc’是’aebycd’的一个子序列,而’ayb’不是。请找出最后一个序列的起始位置。
示例1
输入:
abc
eadbc
输出:
1
示例2
输入:
abc
abcaybec
输出:
3
说明:abcaybec中第0位的abc也匹配,但却不是最后匹配的序列。abcaybec中第3位的aybec去掉字符y、e后也为abc,也与目标字符串相符,故输出最后一个序列aybec的第一个字符的索引位置3。
解题
package com.winyar.algorithm.od;
import java.util.Scanner;
/**
* @Describe 判断字符串子序列
* @Author Winyar
* @Date 2022/6/18
*/
public class SubSequenceLastIndex {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNextLine()) {
String target = sc.nextLine();
String source = sc.nextLine();
int targetLen = target.length();
int sourceLen = source.length();
int i = targetLen - 1;
int j = sourceLen - 1;
// 标识是否有匹配的子序列
boolean flag = false;
// 逆序遍历
while (i >= 0 && j >= 0) {
if (target.charAt(i) == source.charAt(j)) {
if (i == 0) {
// 指针走到target第0位,说明能够匹配完目标字符串
flag = true;
System.out.println(j);
}
i--;
j--;
} else {
// 没有找到相等的字符,继续向左遍历source字符串
j--;
}
}
if (!flag) {
System.out.println(-1);
}
}
sc.close();
}
}
类似题目
参考牛客网题目及解题思路:【查找两个字符串a,b中的最长公共子串】
描述
查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
注:子串的定义:将一个字符串删去前缀和后缀(也可以不删)形成的字符串。请和“子序列”的概念分开!
数据范围:字符串长度1\le length \le300 \1≤length≤300
输入描述:
输入两个字符串
输出描述:
返回重复出现的字符
示例1
输入:
abcdefghijklmnop
abcsafjklmnopqrstuvw
复制
输出:
jklmnop
解题
package com.winyar.niukewang;
import java.util.Scanner;
/**
* @Describe 查找两个字符串a,b中的最长公共子串
* @Author Winyar
* @Date 2022/6/18
*/
public class MaxCommonSubStr {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while (sc.hasNext()) {
String s1 = sc.nextLine();
String s2 = sc.nextLine();
System.out.println(longString(s1, s2));
}
}
// 动态规划
public static String longString(String str1, String str2) {
String temp = "";
// 保证str1是较短字符串
if (str1.length() > str2.length()) {
temp = str1;
str1 = str2;
str2 = temp;
}
int m = str1.length() + 1;
int n = str2.length() + 1;
// 表示在较短字符串str1以第i个字符结尾,str2中以第j个字符结尾时的公共子串长度。
int[][] dp = new int[m][n];
// 公共字串最大长度
int max = 0;
// 记录最大值的str1的结尾下标
int index = 0;
// 从左向右递推,i为短字符串str1的结尾索引,j为str2的结尾索引
for (int i = 1; i < m; i++) {
for (int j = 1; j < n; j++) {
if (str1.charAt(i - 1) == str2.charAt(j - 1)) {
// 相等则计数
dp[i][j] = dp[i - 1][j - 1] + 1;
// 不断更新变量
if (dp[i][j] > max) {
max = dp[i][j];
index = i;
}
}
}
}
// 截取最大公共子串
return str1.substring(index - max, index);
}
}