字符串算法
回顾字符串基本操作
c风格的字符串
char str[]="aaabbbccc";
scanf("%s",str);
int len=strlen(str);
int size=sizeof(str);
cout<<str<<' '<<len<<' '<<size<<endl;
char str2[20];
strcpy(str2,str);
len=strlen(str2);
size=sizeof(str2);
cout<<str2<<' '<<len<<' '<<size<<endl;
strcat(str2,str);
len=strlen(str2);
size=sizeof(str2);
cout<<str2<<' '<<len<<' '<<size<<endl;
strcmp(str,str2);
c++风格的字符串
问题1:创建一个字符串,赋值为空,怎么写?
string s;//默认构造函数,初值为空
//构造函数
String(const char* str = "")
:_str(nullptr)
, _capacity(0)
{
_size = strlen(str);
Reserve(_size);
strcpy(_str, str);
}
// 拷贝构造
String(const String& s)
:_str(nullptr)
, _size(0)
, _capacity(0)
{
String tmp(s._str);
Swap(tmp); // tmp.Swap(*this);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
问题2:创建一个函数,参数为string[]类型s1,返回一个string字符串,为s1数组拼接结果
string f(string s[],int n){
string ss;
for(int i=0;i<n;i++){
ss+=s[i];
}
return ss;
}
问题3:创建一个函数,参数为char[]类型str,返回一个string字符串,为str字符拼接结果
string f(char str[],int n){
string ss;
for(int i=0;i<n;i++){
ss+=str[i];
}
//如果n是str的长度的话,可以这么写
//string ss;
//ss+=str;
//
//或者干脆直接 string ss=str;
return ss;
}
string s;
char ch='A';
char str[]="666";
s+=ch;
s+=str;
s+=s;
cout<<s<<endl;
s+=99999999;
s+=999999999;
String& operator+=(char ch){
PushBack(ch);
return *this;
}
// operator+= 操作符重载 ->字符串
String& operator+=(const char* str){
Append(str);
return *this;
}
String operator+(char ch) const{
String tmp(*this);
tmp.PushBack(ch);
return tmp;
}
//operator+运算符重载 -> 字符串
String& operator+(const char* str){
String tmp(*this);
tmp.Append(str);
return tmp;
}
比较两个字符串相对大小
bool operator<(const String& s)const {
size_t i = 0;
size_t j = 0;
while (i < _size && j < s._size){
if (_str[i] < s[j]){
return true;
}
else if (_str[i] > s[j]){
return false;
}
else{
++i;
++j;
}
}
if (j < s._size){ //左值字符串长度小于右值
return true;
}
else{ //左值字符串长度大于右值
return false;
}
}
bool operator<=(const String& s)const {
return *this < s || *this == s;
}
bool operator>(const String& s)const {
return !(*this <= s);
}
bool operator>=(const String& s)const {
return !(*this < s);
}
bool operator==(const String& s)const {
size_t i = 0;
size_t j = 0;
while (i < _size && j < s._size){
if (_str[i] != s[j]){
return false;
}
else{
++i;
++j;
}
}
if (i == _size && j == s._size){
return true;
}
else{
return false;
}
}
bool operator!=(const String& s)const {
return !(*this == s);
}
string根本上来说,就是封装的字符串类!因为其方便,所以我们能用string来解决问题就不用char[]。
string s="000111";
s[3]='3';
s_str[3]
char& operator[](size_t pos){
assert(pos < _size);
return _str[pos];
}
const char& operator[](size_t pos) const{
assert(pos < _size);
return _str[pos];
}
private://成员变量
char* _str;
size_t _size;
size_t _capacity;
static size_t npos;
底层源码见大神博客
真题
解码
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
string s,res;
cin>>s;
for(int i=0;i<s.size();i++)
{
int k=s[i]-'0';
if(k<=9&&k>1){
for(int j=1;j<k;j++){
res+=s[i-1];
}
}
else{
res+=s[i];
}
}
cout<<res<<endl;
return 0;
}
字符串对比
#include<iostream>
#include<cstdio>
using namespace std;
int ck(string s1,string s2){
if(s1.size()!=s2.size()) return 1;
int n=s1.size();
bool flag=true;
for(int i=0;i<n;i++){
if(tolower(a[i])!=tolower(b[i])){//toupper()
return 4;
}
if(a[i]!=b[i]){
flag=false;
}
}
if(flag==false){
return 3;
}
return 2;
}
int main(){
string s1,s2;
cin>>s1>>s2;
cout<<ck(s1,s2)<<endl;
return 0;
}
FJ的字符串
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
string a="A",b;
int n;
cin>>n;
for(int i=2;i<=n;i++){
b='A'+i-1;
b+=a;
a+=b;
}
cout<<a<<endl;
return 0;
}
日期问题
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int month[]={0,31,28,31,30,31,30,31,31,30,31,30,31};
bool ck(int y,int m,int d){
if(y%4==0&&y%400!=0||y%100==0) month[2]=29;
else month[2]=28;
if(m>12||m<1) return false;
if(d<1||d>month[m]) return false;
return true;
}
string op(int x,int y,int z){
if(x>=60) x+=1900;
else x+=2000;
string s;
s+=(x/1000)+'0';
x%=1000;
s+=(x/100)+'0';
x%=100;
s+=(x/10)+'0';
x%=10;
s+=x+'0';
s+='-';
if(y<10) s+='0';
else s+=y/10+'0',y%=10;
s+=y+'0';
s+='-';
if(z<10) s+='0';
else s+=z/10+'0',z%=10;
s+=z+'0';
return s;
}
int main(){
int a[3];
string s[6];
int cnt=0;
scanf("%d/%d/%d",a,a+1,a+2);
// cout<<a[0]<<' '<<a[1]<<' '<<a[2]<<endl;
// for(int i=0;i<3;i+=2){
// for(int j=0;j<3;j++){
// for(int k=0;k<3;k++){
// if(i!=j&&j!=k&&i!=k&&ck(a[i],a[j],a[k])){
// s[cnt++]=op(a[i],a[j],a[k]);
// }
// }
// }
// }
if(ck(a[0],a[1],a[2])) s[cnt++]=op(a[0],a[1],a[2]);
if(ck(a[2],a[1],a[0])) s[cnt++]=op(a[2],a[1],a[0]);
if(ck(a[2],a[0],a[1])) s[cnt++]=op(a[2],a[0],a[1]);
sort(s,s+cnt);
for(int i=0;i<cnt;i++)
if(i==0||s[i]!=s[i-1]){
cout<<s[i]<<endl;
}
return 0;
}
有用的string函数
getline
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
string s;
getline(cin,s);
cout<<s[0];
for(int i=1;i<s.size();i++){
cout<<' '<<s[i];
}
return 0;
}
insert
#include<iostream>
#include<cstdio>
using namespace std;
int locate(string s){
int idx=0;
for(int i=1;i<s.size();i++){
if(s[i]>s[idx]){
idx=i;
}
}
return idx;
}
int main(){
string s1,s2;
while(cin>>s1>>s2){
int k=locate(s1);
s1.insert(k+1,s2);
cout<<s1<<endl;
}
// string s1="01234",s2="sss";
// s1.insert(0,s2);
// cout<<s1<<endl;
return 0;
}
find
#include<iostream>
#include<cstdio>
using namespace std;
int main(){
string s1,s2;
cin>>s1>>s2;
string ss1=s1;
ss1+=s1;
string ss2=s2;
ss2+=s2;
if(ss1.find(s2)!=-1||ss2.find(s1)!=-1){//find是从左往右找,findr是从右往左找
cout<<"true"<<endl;
}
else cout<<"false"<<endl;
return 0;
}
字符串函数
字符串哈希
从问题入手:回文子串的最大长度
#include<iostream>
#include<cstdio>
using namespace std;
typedef unsigned long long ull;
const int N=100010,P=131;
char str[N];
ull a[N],p[N];
int n;
ull get(int l,int r){return a[r]-a[l-1]*p[r-l+1];}
int main(){
int m;
scanf("%d%d%s",&n,&m,str+1);
p[0]=1;
for(int i=1;i<=n;i++){
p[i]=p[i-1]*P;
a[i]=a[i-1]*P+str[i];
}
int l1,r1,l2,r2;
while(m--){
cin>>l1>>r1>>l2>>r2;
if(get(l1,r1)==get(l2,r2)) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
/*
RE的string
#include<iostream>
#include<string>
using namespace std;
int main(){
string str;
int n,m;
cin>>n>>m>>str;
int l1,r1,l2,r2;
while(m--){
cin>>l1>>r1>>l2>>r2;
if(str.substr(l1-1,r1-l1)==str.substr(l2-1,r2-l2)) cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
*/
kmp字符串匹配算法
从问题入手:剪花布条
#include<iostream>
#include<cstdio>
using namespace std;
const int N=100010,M=1000010;
char ss[N],s[M];
int ne[N];
int n,m;
int main(){
scanf("%d%s%d%s",&n,ss+1,&m,s+1);
for(int i=2,j=0;i<=n;i++){
while(j&&ss[i]!=ss[j+1]) j=ne[j];
if(ss[i]==ss[j+1]) j++;
ne[i]=j;
}
for(int i=1,j=0;i<=m;i++){
while(j&&s[i]!=ss[j+1]) j=ne[j];
if(s[i]==ss[j+1]) j++;
if(j==n){
cout<<i-n<<' ';
}
}
return 0;
}
大数加减乘除算法
从问题入手:黄金连分数
#include<iostream>
#include<cstdio>
#include<vector>
#include<string>
using namespace std;
vector<int> add(vector<int>&A,vector<int>&B){
if(A.size()<B.size()) return add(B,A);
vector<int>C;
int t=0;
for(int i=0;i<A.size();i++){
t+=A[i];
if(i<B.size()) t+=B[i];
C.push_back(t%10);
t/=10;
}
if(t) C.push_back(t);
return C;
}
int main(){
string a,b;
cin>>a>>b;
vector<int>A,B;
for(int i=a.size()-1;~i;i--) A.push_back(a[i]-'0');
for(int i=b.size()-1;~i;i--) B.push_back(b[i]-'0');
auto C=add(A,B);
for(int i=C.size()-1;~i;i--) cout<<C[i];
return 0;
}