151.翻转字符串里的单词
思路
1.先将多余空格去除。
2.翻转整个字符串。
3.对单词逐一翻转。
1:
int fast=0,slow=0,end=s.size()-1;
while(s[fast]==' ')
fast++;
while(s[end]==' ')
end--;//可以先将首尾的空格去除
for(;fast<=end;fast++){
while(fast<=end&&s[fast]==' '&&s[fast-1]==' ')//确保如果有连续多个空格,只填一个
fast++;
s[slow++]=s[fast];
}
s.resize(slow);//重新设置数组大小
or
int fast=0,slow=0;
for(;fast<s.size();fast++){
if(s[fast]!=' '){//1.快指针指向字母时
if(slow!=0){//4.如果不是开头
s[slow]=' ';//4.补上空格
slow++;
}
while(fast<s.size()&&s[fast]!=' '){
s[slow]=s[fast];//2.将单词复制过来
slow++;fast++;
}
}
//3.然后跳过了两个单词的所有空格,快指针直接指向下一个单词的首字母
}
2&3:
reverse(s.begin(),s.end());
int i=0;
for(int j=0;j<=s.size();j++){
if(s[j]==' ' || j==s.size()){
reverse(s.begin()+i,s.begin()+j);
i=j+1;//设置开头
j++;
}
}
右旋字符串
思路
一开始我想的是直接resize扩容,用多余的空间记录后面k个单词,然后用双指针向前填充。
但这样比较麻烦,而且要申请新的空间。
后来看了要求发现只能在本串上操作:
由于要使后面k个到最前面,所以可以先整体翻转,再分别局部翻转。reverse要用到库函数algorithm
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int k;
string s;
cin>>k>>s;
reverse(s.begin(),s.end());
reverse(s.begin(),s.begin()+k);
reverse(s.begin()+k,s.end());
cout<<s;
}
28. 实现 strStr()
28.实现strStr()
KMP算法:
常应用在字符串的查找上。
传统暴力算法遇到不满足的比如在ababad中查找abad,当遇到第四个字母与查找字母d不等时,再从第二个字母开始一一对照。
而KMP算法分析前后缀,因为如果在查找模式串第n个字母时发现不对应,则至少前面都是一一对应的,如果有前缀和后缀相同。
前缀aa 和后缀aa相同,则省去了模式串前缀he文本串b前面aa对比的必要,直接让模式串的j指向前缀的下一个字母b,跳过之前已经匹配过的地方。
计算前缀表
void getnext(int *next,string &s){
int j=0;//prefix,前缀末尾
next[0]=0;//a无相等前缀后缀
for(int i=1;i<s.size();i++){
while(j>0&&s[j]!=s[i]){//当前前缀和后缀的末尾不同,但前面都相同
//所以再往前找最长相同前后缀ffaf(d)ffaf(f)
//d与f不同,
j=next[j-1];
}
if(s[j]==s[i]){
j++;
}
next[i]=j;
}
}
int strStr(string haystack, string neddle) {
vector<int> next(neddle.size());//创建前缀表
getprefixtable(&next[0],neddle);//计算前缀表
for(int j=0,i=0;i<haystack.size();i++){
while(j>0&&haystack[i]!=neddle[j]){
j=next[j-1];
}
if(haystack[i]==neddle[j]){
j++;
}
if(j==neddle.size())
return i-neddle.size()+1;
}
return -1;
}
459.重复的子字符串
枚举
子串的length只可能在[1,n/2]之间,而且必须被整除,子串的特点是j=j-length;、
bool repeatedSubstringPattern(string s) {
for(int length=1;length*2<=s.size();length++){
if(s.size()%length==0){
bool match=true;
int j=length;
for(;j<s.size();j++){
if(s[j]!=s[j-length]){
match =false;
break;
}
}
if(match){
return true;
}
}
}
return false;
KMP算法
找到最长相等前后缀,如果一个字符串有子串,则它的最长相等前后缀不包含的地方则是最小子串。
如果剩余部分刚好能被整除,则可以依次递推使之构成整个字符串,所以为最小子串。
//找到最长相等前后缀,若剩余部分的长度可以被整除,则为最小重复子串
vector<int> next(s.size());
next[0]=0;
for(int j=0,i=1;i<s.size();){
if(j>0&&s[j]!=s[i]){
j=next[j-1];
}
if(s[j]==s[i]){
j++;
next[i]=j;
i++;
}
if(j==0&&s[j]!=s[i]){
next[i]=j;
i++;
}
}
if(s.size()%(s.size()-next[s.size()-1])==0&&next[s.size()-1]!=0)
return true;
else
return false;
}