一、对字符串进行操作
用string处理字符串
防止字符数组存字符串发生难以察觉的越界
优先考虑用string来处理字符串,因为不容易出错而且操作会更简单
#include<iostream>
#include<string>
using namespace std;
int main() {
string s1[] = {"beijing","sdasd"};//string数组可以初始化
cout << s1[0];
string 类型可以直接被字符串或者string进行赋值
string还可以存取字符,其实就相当于简明版的数组类型,甚至可以加减运算
string类型按照词典顺序比较
cout << s1->size();//这里s1指向了第一个元素
str.size()求字符串的长度
str.substr(1,3)//从下标1开始长度为3的子串
char s1[20]; strcpy(s1,str.c_str())//字符串的复制//可放19个字符
char c[5] = "abdc";
string c[5] = { "sda","das","das" };//可以不放满
string s = "123";
}
//0-9之间转化成字符,+‘0’
//其他位数,直接强行赋值int或char得到ASCII码后再转化
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
const int N = 100000;
using namespace std;
int a_[N];
int temp[N];
int digit(int x, int b) {
int j = 0;
while (x > 0) {
a_[j++] = x % b;
x /= b;
}return j;
}
int main() {
int a = 0, b = 0;
cin >> a;
memset(a_, 0, sizeof(int)*N);
cin.get();
int sum = 0;
char str1[100000];
cin.getline(str1, 100000, ' ');
cin >> b;
int flag = 0;
for (int i = 0; str1[i] != '\0'; i++) {
if (str1[i] >= 'a'&&str1[i] <= 'z')
{
temp[i] = str1[i];
temp[i] -= 87;
}
else if (str1[i] >= 'A'&&str1[i] <= 'Z')
{
temp[i] = str1[i];
temp[i] -= 55;
}
else
temp[i] = str1[i] - '0';
flag++;//记录一共有多少位数
}
for (int k = 0; k < flag; k++) {
sum += temp[k] * (pow(a, flag - 1 - k));
}
int m = digit(sum, b);
char lll;
for (int i = m - 1; i >= 0; i--)
if (a_[i] >= 0 && a_[i] <= 9)
cout << a_[i];
else if (a_[i] >= 10) {
lll = a_[i] + 55;
cout << lll;
}
return 0;
}
#include<iostream>
using namespace std;
int main() {
char lll;
lll = 65;
cout << lll;
}
字符数组操作
//如果输入的时候输入长度大于size,那么回车结束,否则以自定义的字符结束
//cin.getline 每次输入前都在等待用户键盘指令
//比如cin输入后会留下空格,ppt上竟然讲了!所以好好复习ppt是有多么重要!!
//所以使用完cin,再加一个cin.get()吃掉回车再用cin.getline
//cin适用于连续输入两个字符串用空格隔开的那种
#include<iostream>
using namespace std;
int main() {
char a[5] = { '0','s','x','s' };
cout<<strchr(a, 's')-a;
return 0;
//}
#include<iostream>
#include<string>
using namespace std;
int main() {
char str1[5];
char str2[5];
cin.getline(str1, 5);
cin.getline(str2, 5);
int cnt;
int n, m;
int max = 0;
for (int i = 0; i < strlen(str1); i++) {
n = i;
for (int j = 0; j < strlen(str2); j++) {
m = j;
if (str1[n] != str2[m] && str2[m] != '\0')
continue;
cnt = 0;
while (str1[n] == str2[m] && str1[n] != '\0'&&str2[m] != '\0')//边界条件时刻牢记
{
cnt++; n++; m++;
}//内层加加不断计数循环,到最后这一轮循环结束就会又重新赋值
max = cnt > max ? cnt : max;
}
}cout << max;
return 0;
}
练习:判断是否为回文子串
//判断是否为回文字串
#include<iostream>
#include<string.h>
using namespace std;
char a[510];
bool panduan(char*a) {//联通字符数组
int left = 0;
int right = strlen(a) - 1;
for (int i = 0; i < strlen(a) / 2; i++)//调控循环长度
{
if (a[left++] == a[right--])//注意left和right都在不断变化
continue;
break;
}
if (left > right)
return true;
else
return false;
}
int main() {
cin.getline(a, 501);
int flag = 0;
int length = strlen(a);
for (int L = 2; L <= length; L++) {//循环字串长度,是可以并且必须取等的
for (int j = 0; j <= length - L; j++)//循环起始段长度
{
flag = 1;
for (int m = j, n = j + L - 1; m < n; m++, n--)
{
if (a[m] == a[n]) {
continue;
}
else {
flag = 0;
break;
}
}
if (flag == 1)
{
for (int k = j; k < L + j; k++)//注意这里为循环的L
cout << a[k];
cout << endl;
}
}
}return 0;
}
二、一些基础代码的默写补充
n-gram
//n-gram
//要提炼出该字串,要逐层比较字串,并且要计数,有第i个字串是多少
#include<iostream>
#include<string.h>
using namespace std;
int main() {
int n;
char str1[501];
int cnt[500] = {};
cin >> n;
cin.get();
cin.getline(str1, 510);
//先提炼字串
int len = strlen(str1);
int i;
for (i = 0; i <= strlen(str1) - n; i++) {//还是先循环字串长度
cnt[i] = 0;//每次计数前先归零
for (int j = i + 1; j <= len - n; j++) {//循环被比较的字串
int flag = 1;
for (int k = 0; k < n; k++) {
if (str1[i + k] != str1[j + k])
{
flag = 0; break;
}//比较部分
}if (flag)cnt[i]++;//有说明可以输出
}
}
int max = 1;
for (i = 0; i <= strlen(str1) - n; i++)
{
max = cnt[i] > max ? cnt[i] : max;
}
cout << max << endl;
for (i = 0; i <= strlen(str1) - n; i++) {
if (cnt[i] == max) {
for (int k = 0; k < n; k++)
cout << str1[k + i];
cout << endl;
}
}
return 0;
汽车限行
汽车限行
#include<iostream>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
char str2[7];
char p(char*str2) {
switch (str2[5]) {
case'1': {return '1'; break; }
case'6': {return '1'; break; }
case'2':case'7': {return '2'; break; }
case'3':case'8': {return '3'; break; }
case'4':case'9': {return '4'; break; }
case'5':case'0': {return '5'; break; }
default: {return '5'; break; }//注意复查最后是字符匹配还是数字匹配,返回的是什么
}
}
int main() {
int leap_year; char yy[5]; char mm[3]; char dd[3];
int tempd;
long long d;
int tempy;
int tempm;
int year[2] = { 365,366 };
int month[2][12] = { {31,28,31,30,31,30,31,31,30,31,30,31},{31,29,31,30,31,30,31,31,30,31,30,31} };
char dayofweek[8] = { '6','7','1','2','3','4','5' };
int n;
char str1[11];
cin >> n;
while (n--) {
tempy = 0;
tempd = 0;
tempm = 0;
d = 0;//总天数清零
cin >> str1 >> str2;//以此实现两个字符串的接续输入
for (int k = 0; k < 4; k++)
yy[k] = str1[k];
for (int k = 5; k <= 6; k++)
mm[k - 5] = str1[k];
for (int k = 8; k <= 9; k++) {
dd[k - 8] = str1[k];
}
tempy = atoi(yy);
tempm = atoi(mm);//别用结构体了直接赋值吧还是
tempd = atoi(dd);
int i = 0;
leap_year = 0;
for (i = 2000; i < tempy; i++) {
leap_year = (i % 4 == 0 && i % 100 != 0 || i % 400 == 0);
d += year[leap_year];
}
leap_year = (tempy % 4 == 0 && tempy % 100 != 0 || tempy % 400 == 0);//更新到tempy再算一遍
if (tempm > 1) {
int R = 0;
for (R = 0; R < tempm - 1; R++)//tempm和tempy要区分开,这就是变量多了自己都会弄混
d += month[leap_year][R];
}
d += tempd;//算出总天数
if ((d - 1) % 7 == 1 || (d - 1) % 7 == 0)
cout << "no" << endl;//看好边界条件,是什么样才输出yes
else if (dayofweek[(d - 1) % 7] == p(str2))//注意边界条件限制,是否计算今天,不计算ok,-1
cout << "yes" << endl;
else
cout << "no" << endl;
}return 0;
}
约瑟夫递推
//约瑟夫递推
#include<iostream>
using namespace std;
int main() {
int n, m, k;
cin >> n >> m >> k;//n只猴报m个
int cnt = 0;
//模拟报数过程+模拟计数过程+模拟查验死亡的过程
int t = 0;
int a[100] = {};
int s = 0;
do
{
++t;
if (t > n) {
t = 1;
}
if (!a[t]) {
s++;
}
if (s == m) {
s = 0;
cnt++;
a[t] = 1;
}
} while (cnt != k);
cout << t;//最后跳出循环的就是终止条件,判断循环中止的子条件
return 0;
}
拆分数据
//1.拆分数据
#include<iostream>
#include<stdio.h>
using namespace std;
int main() {
int digit[50];
int j = 0;
int a;
cin >> a;
while (a != 0) {
digit[j++] = a % 10;//这里是操作了才加一,把j++放在里面真的好用
a = a / 10;
}
while (j--) {
cout << digit[j] << endl;
}
//或者这里也可以循环输出
return 0;
}
//注:此处把j++放在里面减少了写循环的计数的烦恼,输出的时候用while(j--)也是一样的思路
随机数生成
//2.随机数生成
#include<iostream>
#include<stdlib.h>
#include<time.h>
using namespace std;
int main() {
int seed=0, number = 0;
srand((unsigned)time(0));//初始化随机数发生器
while (seed < 1000 || seed>9999)
seed = rand();//验证条件,如果seed生成的不是四位数的随机数
number = seed;
//cout << number;
cout << rand() % 50 << endl;//生成0-49的随机数,原理就是先生成一个数,然后取余
//如果是中间区段的随机数,可以参照上述四位数的生成方法
return 0;
}
数组操作
4.数组操作
#include<iostream>
#include<algorithm>
using namespace std;
bool cmp(int a, int b) {
return a > b;//return a>b,就是降序排,看箭头方向
}
int main() {
int arr[] = { 0,1,2,3,1,2,3,4};
数组正序排列和逆序
//sort(arr, arr + 8,cmp);
//数组正常倒序
int start = 0;
int end = sizeof(arr) / sizeof(arr[0])-1;//注意end要减一才可以
while (start < end) {
int temp = arr[start];
arr[start] = arr[end];
arr[end] = temp;
start++;
end--;
}
for (int i = 0; i < 8; i++)
cout << arr[i] << endl;
return 0;
}
冒泡排序
5.冒泡排序
for (int i = 0; < n - 1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;//
}
}
}
//i负责移动墙,j的遍历在不断减少次数
桶排序
8.桶排序
#include<iostream>
#include<vector>
#include<algorithm>
#include <stdlib.h>
using namespace std;
using std::vector;//注意这句话必写!
int*sort_array(int*arr, int n) {//链接数组用int*arr,返回是数组,返回*
int max_value = 0;
for (int i = 0; i < n; i++) {
if (arr[i] > max_value)
max_value = arr[i];
}
//设置桶的个数
const int bucketnum = 10;
vector<int> buckets[bucketnum];//定义初始桶数
int bucketsize = 1;
while (max_value) {
max_value /= 10;
bucketsize *= 10;//maxvalue相邻大于他最近的10^n
}bucketsize /= bucketnum;//设置好桶
for (int i = 0; i < n; i++) {
int temp = arr[i] / bucketsize;//这个数能归到第几个桶里面
buckets[temp].push_back(arr[i]);
for (int j = (buckets[temp].size()) - 1; j > 0; j--) {//用size也体现了vector的容器本质
if (buckets[temp][j] < buckets[temp][j - 1]) {
int gal = buckets[temp][j];
buckets[temp][j] = buckets[temp][j - 1];
buckets[temp][j - 1] = gal;
}//这里加一个随机排序,因为数据不是很多,所以输入一个排一个就行
}
}//如果数目较多,可以依次访问每个桶,进行sort
for (int i = 0, k = 0; i < bucketnum; i++) {
for (int j = 0; j < int(buckets[i].size()); j++)//为什么这里要加一个int呢?
arr[k++] = buckets[i][j];
}
return arr;
}
using namespace std;
int main() {
int arr[] = { 12,5,4,7,6,4,1,2,6 };
sort_array(arr, 9);
for (int i = 0; i < 9; i++)
cout << arr[i];//如果让倒序排,那就用while(length--)就可以
}
删除最大数和最小数(可以泛化)
//9.删除最大数和最小数————可以泛化
int del(int*a, int n) {
int maxi, mini, i, j;
maxi = mini = 0;
for (int i=1; i < n; i++) {
if (a[i] > a[maxi])
maxi = i;
else if (a[i] < a[mini])
mini = i;
}
for (int i = 0, j = 0; i < n; i++)
if (i != maxi && i != mini)
a[j++] = a[i];//自习琢磨这个列表的执行逻辑,前期j=i,直到i=maxi了,i跳过+1,j依然等于前值,实现数据前移
return j;//返回删除后的数组个数。改成int*,可以返回删除后的列表
}
护林员盖房子
10.护林员盖房子
#include<iostream>
#include<algorithm>
using namespace std;
int main() {
int m, n;
cin >> m >> n;
int a[21][21] = {};
for (int i = 1; i <=m; i++) {
for (int j = 1; j <=n; j++) {
int temp;
cin >> temp;
if (temp == 0)
a[i][j] = 1;
else
a[i][j] = 0;//先完成树木和空地的转化
}
}
for (int i = 1; i <=m; i++) {
for (int j = 1; j <= n; j++) {
if (a[i][j] != 0)
a[i][j] = a[i][j - 1] + 1;
}
}
int max = 0;
int length, width = 1;
int area = 0;
for(int i=1;i<=m;i++)
for (int j = 1; j <= n; j++) {
if (a[i][j] != 0) {
width = 1;
length = a[i][j];
area = length * width;
max = area > max ? area : max;
int minlength = a[i][j];//再用一下向上遍历搜索
for (int k = i - 1; k >= 1; k--) {
if (a[k][j] == 0)break;
minlength = a[k][j] < minlength ? a[k][j] : minlength;//因为这里有更新,所以不能在for内定义变量,否则就轮转不了了
width++;
area = minlength * width;//向上向左检索
max = area > max ? area : max;
}
}
}
cout << max;
return 0;
}
进制转化
//进制转换
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
const int N = 100000;
using namespace std;
int a_[N];
int temp[N];
long digit(long long x, int b) {
long j = 0;
while (x > 0) {
a_[j++] = x % b;
x /= b;
}return j;
}
int main() {
int a = 0, b = 0;
cin >> a;
memset(a_, 0, sizeof(int)*N);//记得初始化
cin.get();
long long sum = 0;
char str1[1000000];
cin.getline(str1, 1000000, ' ');
cin >> b;
int flag = 0;
for (int i = 0; i <= strlen(str1) - 1; i++) {
if (str1[i] >= 'a'&&str1[i] <= 'z')
{
temp[i] = str1[i];
temp[i] -= 87;
}
else if (str1[i] >= 'A'&&str1[i] <= 'Z')
{
temp[i] = str1[i];
temp[i] -= 55;
}
else
temp[i] = str1[i] - '0';
flag++;//记录一共有多少位数
}
for (int k = 0; k < flag; k++) {
sum += temp[k] * (pow(a, flag - 1 - k));
}
long m = digit(sum, b);
char lll;
for (int i = m - 1; i >= 0; i--)
if (a_[i] >= 0 && a_[i] <= 9)
cout << a_[i];
else if (a_[i] >= 10) {
lll = a_[i] + 55;
cout << lll;
}
return 0;
}
大整数乘除法
大整数乘法,进位规则变成取模,需要找一个新数组储存双循环新数组标位i+j因为乘法每个都要循环到
大整数除法的迭代思路:(r*10+num[i]-‘0’)%k
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
const int N = 100000;
using namespace std;
int a_[N];
int temp[N];
int digit(int x, int b) {
int j = 0;
while (x > 0) {
a_[j++] = x % b;
x /= b;
}return j;
}
int main() {
int a = 0, b = 0;
cin >> a;
memset(a_, 0, sizeof(int)*N);
cin.get();
int sum = 0;
char str1[100000];
cin.getline(str1, 100000, ' ');
cin >> b;
int flag = 0;
for (int i = 0; str1[i] != '\0'; i++) {
if (str1[i] >= 'a'&&str1[i] <= 'z')
{
temp[i] = str1[i];
temp[i] -= 87;
}
else if (str1[i] >= 'A'&&str1[i] <= 'Z')
{
temp[i] = str1[i];
temp[i] -= 55;
}
else
temp[i] = str1[i] - '0';
flag++;//记录一共有多少位数
}
for (int k = 0; k < flag; k++) {
sum += temp[k] * (pow(a, flag - 1 - k));
}
int m = digit(sum, b);
char lll;
for (int i = m - 1; i >= 0; i--)
if (a_[i] >= 0 && a_[i] <= 9)
cout << a_[i];
else if (a_[i] >= 10) {
lll = a_[i] + 55;
cout << lll;
}
return 0;
}