翻转字符串里的单词
AC
主要思路是去空格然后保存在vector 里面。
class Solution {
public:
string reverseWords(string s) {
vector<string> v;
string h="";
string ans="";
for(int i=0;i<s.size();i++)
{
while(s[i]==' '&&i<s.size())//处理前面空格
{
i++;
}
h+=s[i];
if(i+1<s.size()){ // 要用i+1一定要先判断
if(s[i+1]==' ')
{
v.push_back(h);
h="";
while(s[i+1]==' '&&i<s.size()) i++; //处理中间和末尾空格
}
}
}
if(h.size()>0) v.push_back(h);
string res="";
for(int i=v.size()-1;i>=0;i--)
{
if(i==0) res+=v[i];
else res+=v[i]+" ";
}
return res;
}
};
C++中的substr()函数详解
在C ++中,substr()是用于字符串处理的预定义函数。string.h是字符串函数所需的头文件。
此函数将两个值pos和len作为参数,并返回一个新构造的字符串对象,其值初始化为该对象的子字符串的副本。从pos开始复制字符串,直到pos + len表示[pos,pos + len)为止。
重要事项:
第一个字符的索引为0(不是1)。
如果pos等于字符串长度,则该函数返回一个空字符串。
如果pos大于字符串长度,则抛出out_of_range。如果发生这种情况,则字符串中没有任何更改。
如果对于所请求的子字符串len大于字符串的大小,则返回的子字符串为[pos,size())。
句法:
字符串substr(size_t pos,size_t len)const;
参数:
pos:要复制的第一个字符的位置。len:子字符串的长度。size_t:这是一个无符号整数类型。返回值:返回一个字符串对象。
输出:字符串是:ook
右旋字符串
AC
一种用substr,一种用for字符串拼接 见代码和代码注释部分
#include <iostream>
#include <cstdio>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include<list>
#include <set>
#include <ctime>
#include<unordered_map>
#include <bitset>
#include<random>
#include<regex>
#include <chrono>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
#define pr pair<double,int>
#define tp tuple<int,int,int>
const int N = 2e6 + 7;
const int mod = 998244353;
ll a[N],s[N];
ll n, m, k;
ll e[N];
ll ne[N];
ll head,idx;
void solve()
{
int k;
string s;
cin>>k>>s;
string x="";
string i=s.substr(s.size()-k,k);
string j=s.substr(0,s.size()-k);
x=i+j;
// for(int i=s.size()-k;i<s.size();i++)
// x+=s[i];
// for(int i=0;i<s.size()-k;i++) x+=s[i];
cout<<x;
}
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);//提高cin、cout的输入输出效率
solve();
}
KMP算法总结
算法思想
KMP算法(Knuth-Morris-Pratt算法)是一种高效的字符串匹配算法,用于在主串中查找模式串出现的位置。其核心思想是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数。
核心概念
部分匹配表(Partial Match Table):也称为next数组,记录模式串前缀和后缀的最长公共元素长度
失配处理:当字符不匹配时,根据next数组回溯模式串的位置,避免重新匹配已匹配的部分
算法步骤
- 构建next数组(预处理模式串)
// 0-indexed实现
ne[0] = -1;
for (ll i = 1, j = -1; i < n; i++) {
while (j >= 0 && p[i] != p[j + 1]) j = ne[j];
if (p[i] == p[j + 1]) j++;
ne[i] = j;
}
// 1-indexed实现
for (ll i = 2, j = 0; i <= n; i++) {
while (j && p[i] != p[j + 1]) j = ne[j];
if (p[i] == p[j + 1]) j++;
ne[i] = j;
}
- 使用next数组进行匹配
// 0-indexed实现
for (ll i = 0, j = -1; i < m; i++) {
while (j >= 0 && s[i] != p[j + 1]) j = ne[j];
if (s[i] == p[j + 1]) j++;
if (j == n - 1) {
cout << i - n + 1 << " ";
j = ne[j];
}
}
// 1-indexed实现
for (ll i = 1, j = 0; i <= m; i++) {
while (j && s[i] != p[j + 1]) j = ne[j];
if (s[i] == p[j + 1]) j++;
if (j == n) {
cout << i - n << " ";
j = ne[j];
}
}
两种实现方式对比
关键点解析
next数组作用:
记录模式串的最长相同前后缀长度
当匹配失败时,指示模式串指针应该回溯的位置
匹配过程:
主串指针i只增不减,一直向前移动
模式串指针j根据匹配情况在next数组指导下回溯
当j达到模式串长度时表示匹配成功
时间复杂度:
构建next数组:O(n)
匹配过程:O(m)
总时间复杂度:O(n+m)
#include <iostream>
#include <cstdio>
#include <fstream>
#include <iomanip>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include<list>
#include <set>
#include <ctime>
#include<unordered_map>
#include <bitset>
#include<random>
#include<regex>
#include <chrono>
#include<unordered_map>
#include<unordered_set>
using namespace std;
typedef long long ll;
#define pr pair<double,int>
#define tp tuple<int,int,int>
const int N = 1e6 + 7;
const int mod = 998244353;
char s[N],p[N];//s是模式串,p是主串
ll ne[N];
void solve()
{
ll n,m;
cin>>n>>p+1>>m>>s+1;
//匹配成功的
for(ll i=2,j=0;i<=n;i++)
{
while(j&&p[i]!=p[j+1]) j=ne[j];
if(p[i]==p[j+1]) j++;
ne[i]=j;
}
for(ll i=1,j=0;i<=m;i++)
{
while(j&&s[i]!=p[j+1]) j=ne[j];
if(s[i]==p[j+1]) j++;
if(j==n)
{
cout<<i-n<<" ";
j=ne[j];
}
}
}
int main()
{
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(false);//提高cin、cout的输入输出效率
solve();
}
实现 strStr()
AC
find:
class Solution {
public:
int strStr(string haystack, string needle) {
return haystack.find(needle);
}
};
kmp:
class Solution {
public:
int strStr(string haystack, string needle) {
int n=needle.size();
int m=haystack.size();
const int N=1e5;
int ne[N];
memset(ne,0,sizeof(ne));
ne[0]=-1;
//求匹配表
for(int i=1,j=-1;i<n;i++)
{
while(j>=0&&needle[j+1]!=needle[i]) j=ne[j];
if(needle[j+1]==needle[i]) j++;
ne[i]=j;
}
//匹配成功
for(int i=0,j=-1;i<m;i++)
{
while(j>=0&&needle[j+1]!=haystack[i]) j=ne[j];
if(needle[j+1]==haystack[i]) j++;
if(j==n-1)
{
return i-j;
j=ne[j];
}
}
return -1;
}
};
重复的子字符串
AC
KMP做法:
class Solution {
public:
bool repeatedSubstringPattern(string s) {
int n=s.size();
const int N=1e4+5;
int ne[N];
memset(ne,0,sizeof(N));
ne[0]=-1;
for(int i=1,j=-1;i<n;i++)
{
while(j>=0&&s[i]!=s[j+1]) j=ne[j];
if(s[i]==s[j+1]) j++;
ne[i]=j;
}
if(n%(n-(ne[n-1]+1))==0&&ne[n-1]!=-1) return true;
else return false;
}
};