题目场景: 2022.10.16 亚信安全笔试
😘最长回文子串
题库链接:
|力扣: leetcode.cn|LeetCode: leetcode.com|
题目: 给你一个字符串 s,找到 s 中最长的回文子串。
解析: 采用两种思路可以解决: 动态规划 和 中心扩散
动态规划
通过分析可知, 当第i个字符到第j个字符为回文串的同时, 如果i-1位于j+1位相同, 此时第i-1位到j+1位仍为回文串, 根据此内容进行动态规划, 可写出如下代码:
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
if (n < 2) return s;
int begin = 0;
int end = 0;
boolean[][] dp = new boolean[n][n];
for (int i = 0; i < n; i++) {
dp[i][i] = true;
}
char[] chars = s.toCharArray();
int j;
for (int len = 2; len <= n; len++) {
for (int i = 0; i < n; i++) {
j = i + len - 1;
if (j >= n) break;
if (chars[i] != chars[j]) dp[i][j] = false;
else if (len < 4) dp[i][j] = true;
else dp[i][j] = dp[i + 1][j - 1];
if (dp[i][j] && len > (end - begin + 1)) {
begin = i;
end = j;
}
}
}
return s.substring(begin, end + 1);
}
中心扩散
第二种思路同样基于状态转移方程, 不过于动态规划的广度优先不同, 本方法通过不断修改中心点, 尽可能得到每个点的最长回文串, 当左右相同时,则继续向外扩展
class Solution {
public String longestPalindrome(String s) {
if (s.length() < 2) return s;
int begin = 0, end = 0;
for (int i = 0; i < s.length(); i++) {
int len1 = expendCenter(s, i, i);
int len2 = expendCenter(s, i, i + 1);
int len = Math.max(len1, len2);
if (len > end - begin) {
begin = i - (len - 1) / 2;
end = i + len / 2;
}
}
return s.substring(begin, end + 1);
}
private int expendCenter(String s, int i, int j) {
while (i >= 0 && j < s.length() && s.charAt(i) == s.charAt(j)) {
i--;
j++;
}
return j - i - 1;
}
}
🥰正则表达式匹配
题库链接:
|力扣: leetcode.cn|LeetCode: leetcode.com|
题目:
给你一个字符串 s 和一个字符规律 p,请你来实现一个支持 “.” 和 “*” 的正则表达式
“.” 匹配任意单个字符
“*” 匹配零个或多个前面的那一个元素
所谓匹配,是要涵盖整个字符串 s的,而不是部分字符串。
解析: 采用动态规划解决此题
动态规划
当p的j位字符为正常字符或者点号时, 只要能与s的i位匹配, 则两者的匹配状态等同于前i-1和前j-1位字符串的匹配状态, 如果这两位不匹配则直接返回不匹配即可
对于p的j位字符为星号时,需要分类判断
若p的j位字符为星号, 则p的j-1位可以出现0次或多次
- 若出现0次, 则是否匹配取决于p的前j-2与s是否匹配
例如s=abc和p=abcd* - 若出现多次, 则首先判断s的最后一位是否匹配p的允许多次出现的字符, 即j-1位
例如s=abcddd和p=abcd*
若该位匹配则状态等同于s的前i-1位与p的匹配状态
如s=abcdd和p=abcd*
直至s=abc和p=abcd*, 这时等同于出现0次
class Solution {
public boolean isMatch(String s, String p) {
int m = s.length();
int n = p.length();
boolean[][] dp = new boolean[m + 1][n + 1];
dp[0][0] = true;
for (int i = 0; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (p.charAt(j - 1) == '*') {
dp[i][j] = dp[i][j - 2];
if (match(s, p, i, j - 1)) {
dp[i][j] = dp[i][j] || dp[i - 1][j];
}
} else {
if (match(s, p, i, j))
dp[i][j] = dp[i - 1][j - 1];
}
}
}
return dp[m][n];
}
private boolean match(String s, String p, int i, int j) {
if (i == 0) {
return false;
}
if (p.charAt(j - 1) == '.') {
return true;
}
return s.charAt(i - 1) == p.charAt(j - 1);
}
}