Leetcode刷题之路-字符串类型1
214.最短回文串
给定一个字符串s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例:
输入:"aacecaaa"
输出:"aaacecaaa"
输入:"abcd"
输出:"dcbabcd"
自己的解决方法:暴力解法
- [ 申请另外一个string空间b ]
- [ char两根指针,一根固定在字符串起始地址,一根指向字符串末尾 ]
- [ 判断这个范围的字符串是否回文,若不是回文,把末尾字符填进字符空间b,尾指针前移 ]
- [ 循环上述步骤直至判断出某个范围的字符串是回文 ]
- [ 这时候把传进来的字符串append到字符串b的后面就得出结果了 ]
string shortestPalindrome(string s) {
int len = s.size();
string cutstr;
for (int i = 0; i < len; i++) {
char* pStart = &s[0]; //指向字符串起始地址
char* pEnd = &s[len - (i + 1)]; //指向字符串最后一个字符的地址
if (!IfPalindrome(pStart, pEnd, len - i)) {
cutstr += (*pEnd); //判断不是回文,拼接到另一块字符串空间中
}
else {//判断到连续的最长回文子串了
if (cutstr.size() == 0) {//排除目标字符串本身就是回文串的情况
return s;
}
else {//把目标字符串拼接到剪下来的字符串后面就可以了
return cutstr.append(s);
}
}
}
return cutstr.append(s);//一般不会跑到这里,只是为了通过编译
}
bool IfPalindrome(char* pStart, char* pEnd, int len) {//判断字符串是否回文字符串
for (int i = 0; i < len; i++) {
if (*pStart++ != *pEnd--) {
return false;
}
}
return true;
}
5.最长回文子串
给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例:
输入:"babad"
输出:"bab"或"aba"
输入:"cbbd"
输出:"bb"
自己的解决方法:双指针缩小范围遍历字符串
- [ 直接开始遍历 ]
- [ char两根指针,初始时一根指向头,一根指向(尾-i) ]
- [ while循环里判断,头指针到尾指针这段字符串是否满足回文条件,满足直接截取这段字符串返回 ]
- [ 不满足条件,把头指针和尾指针双双右移一位,直到尾指针指向了s字符串的最后一个字符 ]
- [ while里都不满足的话,就缩小搜索范围,pStart还是指向头,pEnd就相对上一次左移一位了 ]
- [ 循环往复,直到找到第一个满足回文条件的回文,直接返回 ]
- [ 因为是从最大开始判断的,所以只要找到满足条件,那肯定就是最大咯 ]
string longestPalindrome(string s) {
int len = s.size();
string result = "";
for (int i = 0; i < len; i++) {
char* pStart = &s[0]; //一根指针指向字符串头
char* pEnd = &s[len - (i + 1)]; //一根指向字符串最后一个字符地址
while (pEnd <= & s[len - 1]) { //这个循环实现头尾长短不变,但是搜索范围往前移动的结构
if (!IfPalindrome(pStart, pEnd, pEnd - pStart + 1)) {//判断不是回文串
pStart++;
pEnd++; //两根指针同时往后移一格
}
else { //搜索到回文串
int resultlen = pEnd - pStart + 1; //此时两个指针包括的元素个数就是回文串的长度
for (int i = 0; i < resultlen; i++) {
result.append(1,*(pStart+i)); //把元素拼接到result返回
}
return result;
}
}
}
return result; //跑到这里表示没有找到任何回文串,就是返回空
}
bool IfPalindrome(char* pStart, char* pEnd, int len) {
for (int i = 0; i < len; i++) {
if (*pStart++ != *pEnd--) {
return false;
}
}
return true;
}
剑指offer 58 -II.左旋转字符串
字符串的左旋转操作是把字符串前面的若干个字符转移到字符串的尾部。请定义一个函数实现字符串左旋转操作的功能。比如,输入字符串"abcdefg"和数字2,该函数将返回左旋转两位得到的结果"cdefgab"。
示例:
输入: s = "abcdefg", k = 2
输出: "cdefgab"
输入: s = "lrloseumgh", k = 6
输出: "umghlrlose"
- [ 直接用substr返回n到最后的字符串,然后把0到n的字符串拼接上去 ]
string reverseLeftWords(string s, int n) {
return s.substr(n) + s.substr(0,n); //就是把尾变成头,头变成尾
}
KMP算法(c++)
KMP主算法参考
int match (char* P, char* S){ // KMP 算法
int* next = buildNext(P); // 构造 next 表
int m = (int) strlen (S), i = 0; // 文本串指针
int n = (int) strlen(P), j = 0; //模式串指针
while (j < n && i < m) // 自左向右逐个比对字符
if (0 > j || S[i] == P[j]) // 若匹配,或 P 已移除最左侧
{i++; j++} // 则转到下一字符
else
j = next[j]; // 模式串右移(注意:文本串不用回退)
delete [] next; // 释放 next 表
return i - j;
}
构造next表参考
int* buildNext(char* P) { // 构造模式串 P 的 next 表
size_t m = strlen(P), j = 0; // “主”串指针
int* N = new int[m]; // next 表
int t = N[0] = -1; // 模式串指针
while (j < m - 1)
if ( 0 > t || P[j] == P[t]){ // 匹配
j++; t++;
N[j] = t; // 此句可改进为 N[j] = (P[j] != P[t] ? t : N[t]);
}else // 失配
t = N[t];
return N;
}