常用C/CPP的算法


前言: 我们经过了大部分的学习我们也对于一门计算机语言有了初步的了解。数据结构+算法是重要的。我们开始逐个分析。
我把 我刷题过程中 遇到的问题总结起来大多就是一下内容

整型上升:

    printf("%d\n", n % 2 ? n / 2 + 1 : n / 2);

只保留一次:

for (i = 1; i < n; i++)
{
    if (arr[i] != arr[i - 1])
    {
        arr[uniqueCount] = arr[i];
        uniqueCount++;
    }
printf("%d\n", uniqueCount);

一、日期问题:

1.1>闰年

四年一闰,百年不闰,四百年再闰。
下面是1000-2000中闰年输出

#include <iostream>
using namespace std;

int main() {
    int year;
    for (year = 1000; year <= 2000; year++) {
        // 能被4整除并且不能被100整除,或者能被400整除的是闰年
        if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
            cout << year << endl;
        }
    }
}

判断是不是闰年

#include <stdio.h>
int is_leap_year(int y){
    if((y%4==0&&y%100!=0)||(y%400==0))
           return 1;
           //在这里
    else
            return 0;
}
int main(){
    int year=0;
    int count=0;
    //如果初试的year是4的倍数的话year++可以替换为year+=4
    for(year=1000;year<=2000;year++){
        //判断year是否为闰年
        if(is_leap_year(year)==1){
            count++;
            printf("%d\n",year);
            printf("%d",count);
        }
    }
    return 0;
}

1.2>计算指定的年月日是星期几

利用:基姆拉尔森计算公式(Kim larsen calculation formula)。

公式:W= (d+2m+3(m+1)/5+y+y/4-y/100+y/400+1)%7

注意事项:

1)d表示日期中的日数,m表示月份数,y表示年数。
w表示星期,w的取值范围是0~6, 0代表星期日,6星期一到星期六。

2)一月和二月看成是上一年的十三月和十四月

3)上述除法均为整数

1.3>判断日期是否合法

这个常常是用在给定某年某月某日—到某年某月某日结束中有多少个回文日期【如同20200202】,或者连续递增的日子【带有123升序的日子】

int months[]={0,31,28,31,30,31,30,31,31,30,31,30,31};

int check_day(int data)
{
	int year=data/10000;
	int month=data%10000/100;
	int day=data%100;
	if(month<=0||month>=13||day<=0) return 0;
	if(month!=2&&day>months[month]) return 0;
	 if(month == 2) {
        if((year % 4 == 0&& year % 100 != 0) || (year % 400 == 0)){
            if(day > 29) return 0;
            }else if( day > 28) return 0;
    }
    return 1;
}

测试:

#include <iostream>
using namespace std;

int months[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

bool checkDay(int date) {
    int year = date / 10000;
    int month = date % 10000 / 100;
    int day = date % 100;
    if (month <= 0 || month >= 13 || day <= 0) return false;
    if (month != 2 && day > months[month]) return false;
    if (month == 2) {
        if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
            if (day > 29) return false;
        } else if (day > 28) return false;
    }
    return true;
}

int main() {
    int date1 = 20220202; // 合法日期
    int date2 = 20221345; // 非法日期
    if (checkDay(date1)) {
        cout << "日期 " << date1 << " 合法" << endl;
    } else {
        cout << "日期 " << date1 << " 不合法" << endl;
    }
    if (checkDay(date2)) {
        cout << "日期 " << date2 << " 合法" << endl;
    } else {
        cout << "日期 " << date2 << " 不合法" << endl;
    }
    return 0;
}

二、一般数的运用

2.1>约数

2.1.1判断是不是其约数

bool isFactor(int m, int n) {
    if (n == 0) {
        // n不是m的约数。
        return false;
    }
    if (m % n != 0) {
        // n不是m的约数。
        return false;
    }
    if (m % n == 0 || n == 1 || m == 0) {
        // n是m的约数。
        return true;
    }
    return false;
}

2.1.2 N 的约数

 int n;
    for (int i = 1; i <= n ; i ++)
        if (n % i == 0)
        printf("%d",i);

2.1.3最大公因数gcd

法一 return递归:
 int gcd(int a,int b){ return b?gcd(b,a%b):a; }
法二 欧几里得算法
#include <iostream>
using namespace std;

// 欧几里得算法,计算最大公约数
int euclideanAlgorithm(int a, int b) {
    while (b) {
        int temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}

int main() {
    int a, b;
    cin >> a >> b;
    cout << euclideanAlgorithm(a, b);
    return 0;
}

2.1.4最小公倍数lcm

 int lcm(int a,int b){ return a/gcd(a,b)*b; }

2.1.5 约数个数

普通
#include <iostream>
using namespace std;

// 计算约数个数
int countDivisors(int n) {
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (n % i == 0) {
            cnt++;
        }
    }
    return cnt;
}

int main() {
    int n;
    // 调用函数计算约数个数
    int result = countDivisors(n);
    cout << "约数个数为: " << result << endl;
    return 0;
}
简化(剪枝):

同下方素数里面的一项一样,开根号,将n开根号。
因为A*B=n;
当我们得知A是约数时候,那么B也一定是n的约数。

缩小了枚举的范围: 1~sqrt(n)
而且每次循环仅仅统计A和B的个数即可,且需要在以的是需不需要考虑A=B的情况

2.1.6约数之和

在这里插入图片描述

#include <stdio.h>
int main(){
 int i,a,sum;
 while(scanf("%d",&a)!=EOF){
  
  sum=0;
  for(i=1;i<=a;i++)
   if(a%i==0)
    sum+=i;
    //printf("%d ,",i);
  printf("得出约数和为%d\n",sum);  
 }
 return 0;
}

2.2>素数

先写两种范围行个数的。

法一 试除法:

#include <stdio.h>
int main(){
int i=0,count=0;
for(i=100;i<=200;i++){
    int j=0;
    for(j=2;j<i;j++){
        if(i%j==0){
            break;
        }
    }
    if(j==i){
        count++;
        printf("%d",i);
    }
}
printf("\n count=%d ",coount);
}

#include <iostream>
using namespace std;

// 判断一个数是否为素数
bool isPrime(int num) {
    for (int i = 2; i < num; i++) {
        if (num % i == 0) {
            return false;
        }
    }
    return true;
}

int main() {
    int count = 0;
    for (int i = 100; i <= 200; i++) {
        if (isPrime(i)) {
            count++;
            cout << i << " ";
        }
    }
    cout << "\n count=" << count;
    return 0;
}

法二 开平方:

要用到<math.h>中的sqrt

函数原型:
double sqrt(double x)

#include <stdio.h>
#include <math.h>
int main(){
    //i=a*b    那么a和b里至少有一个数字<=开平方i
    //sqrt--开平方的数学库函数
    int i=0,count=0;
    for(i=101;i<=200;i++){
        int j=0;
        for(j=2;j<=sqrt(i);j++){
            if(i%j==0){
                break;
            }
        }
        if(j>sqrt(i)){
            count++;
            printf("%d\n",i);
        }
    }
    printf("%d个·",count);
    
}

实际上在较大数,难以控制数字的时候
为了防止实数的运算过程中的精度丢失 我们不应该开平方

解决办法: 将第二层for循环中改成 j*j的形式

for(j=2;j*j<=(i);j++){
            if(i%j==0){
                break;

而为了不使得数据过大,那就j<=(i/j)

for(j=2;j<=(i/j);j++){
            if(i%j==0){
                break;
#include <iostream>
#include <cmath>
using namespace std;

// 素数
void primeNumbers(){
    //i=a*b    那么a和b里至少有一个数字<=开平方i
    //sqrt--开平方的数学库函数
    int i=0,count=0;
    for(i=101;i<=200;i++){
        int j=0;
        for(j=2;j<=sqrt(i);j++){
            if(i%j==0){
                break;
            }
        }
        if(j>sqrt(i)){
            count++;
            cout << i << endl;
        }
    }
    cout << count << "个·";
}

int main(){
    primeNumbers();
    return 0;
}

接下来是判断素数的

法三:埃式筛法

原理:素数的倍数一定是合数
要得到自然数n以内的全部素数,必须把不大于根号n的所有素数的倍数剔除,剩下的就是素数。
用excel打的表格
这个算法唯一点就是,合数一般都要被重复判断。
比如:6这个数字既是2的倍数,又是3的倍数,在for循环的过程中重复被标记为false

#include<stdio.h>
const int max=1e8+1;
int arr[max];
int main(){
	int n,cnt=0;
	scanf("%d",&n);
	for(int i=1;i<=max;i++){
		arr[i]=1;
	} 
	for(int i=2;i*i<=n;i++)
	  if(arr[i])
	  for(int j=i*i;j<=n;j+=i)
	  arr[j]=0;
	  for(int i=2;i<=n;i++)
	     if(arr[i])printf("%d ",i);

} 

简化:

#include<stdio.h>
const int max=1e8+1;
int arr[max];
int main(){
	int n,cnt=0;
	scanf("%d",&n);
	for(int i=1;i<=max;i++){
		arr[i]=1;
	} 
	for(int i=2;i<=n;i++){
		if(arr[i]){
		printf("%d\n",i);
		cnt++;}
		for(int j=i*i;j<=n;j+=i)//j就是n以内的i的倍数
		arr[j]=0;
	}
	printf("%d",cnt);
} 
#include <iostream>
using namespace std;

void sieveOfEratosthenes(int n) {
    int max = 1e8 + 1;
    int arr[max];
    int cnt = 0;

    for (int i = 1; i <= max; i++) {
        arr[i] = 1;
    }

    for (int i = 2; i <= n; i++) {
        if (arr[i]) {
            cout << i << " ";
            cnt++;
        }
        for (int j = i * i; j <= n; j += i) {
            arr[j] = 0;
        }
    }
    cout << endl << cnt;
}

int main() {
    int n;
    cin >> n;
    sieveOfEratosthenes(n);
    return 0;
}

法四:欧拉筛法

约数与约数的乘法一定是合数4=22;8=24=222

#include<stdio.h>
const int max=1e8+1;
int arr[max],prime[max],t;
int main(){
	int n,cnt=0;
	scanf("%d",&n);
	for(int i=1;i<=max;i++){
		arr[i]=1;
	} 
	for(int i=2;i<=n;i++){
		if(arr[i]){
		prime[cnt++]=i;
		printf("%d\n",i);
		}
		for(int j=0;j<cnt&&( t=i*prime[j])<=n;j++)//j就是n以内的i的倍数
		{arr[t]=0;
		if(i%prime[j]==0)break;}
	}
	printf("%d",cnt);
} 
#include <iostream>
using namespace std;

const int max = 1e8 + 1;
int arr[max], prime[max], t;

void primeSieve(int n) {
    int cnt = 0;
    for (int i = 1; i <= max; i++) {
        arr[i] = 1;
    }
    for (int i = 2; i <= n; i++) {
        if (arr[i]) {
            prime[cnt++] = i;
            cout << i << endl; // 输出素数
        }
        for (int j = 0; j < cnt && (t = i * prime[j]) <= n; j++) {
            arr[t] = 0;
            if (i % prime[j] == 0) break;
        }
    }
    cout << cnt; // 输出素数的个数
}

int main() {
    int n;
    cin >> n;
    primeSieve(n);
    return 0;
}

2.3>快速幂

快速幂就是快速算底数的n次幂。其时间复杂度为 O(log₂N)。

和初中学习幂次的道理一样

法一 位操作符

#include <iostream>
using namespace std;

// 快速幂法一(位操作符)
int fastPower(int base, int exponent) {
    int result = 1;
    while (exponent > 0) {
        if (exponent & 1) {
            result *= base;
        }
        base *= base;
        exponent >>= 1;
    }
    return result;
}
#include <iostream>

using namespace std;

// 快速幂 法一 位操作符
int qp(int n, int m, int p) {
    int res = 1;
    
    while (m > 0) {
        if (m & 1) {  // 检查 m 是否为奇数
            res = (long)res * n % p;
        }
        m >>= 1;      // 右移 m
        n = (long)n * n % p;
    }
    
    return res;
}
   

法二:return递归:

不推荐用return,容易爆表,占地较大

#include <iostream>

using namespace std;

// 快速幂 return递归
int qp(int a, int b) {
    if (b == 0) return 1;
    if (b == 1) return a;
    if (b % 2 == 0) return qp(a, (b / 2)) * qp(a, (b / 2));
    if (b % 2 == 1) return qp(a, (b / 2)) * qp(a, (b / 2)) * a;
}

int main() {
    int a, b;
    cin >> a >> b;
    cout << qp(a, b);
}

2.4>快速乘

与快速幂相似

#include <iostream>

using namespace std;

// 快速乘
int qmul(int n, int m, int p) {
    int res = 0;

    while (m > 0) {
        if (m & 1) { // 判断是不是奇数
            res = (res + n) % p;
        }
        m >>= 1; // 右移 利用了一点二分法的思路
        n = (n + n % p) % p;
    }

    return res;
}

2.5>斐波那契数列

“兔子数列”。F(0)=0,F(1)=1, F(n)=F(n - 1)+F(n - 2)(n ≥ 2,n ∈ N*)
在这里插入图片描述

2.5.1通项公式写出某一项

#include <iostream>
#include <cmath>
using namespace std;

double fibonacci(int n) {
    double ret;
    ret = (pow(((1 + sqrt(5)) / 2), n) - pow(((1 - sqrt(5)) / 2), n)) / sqrt(5);
    return ret;
}

int main() {
    int n;
    cin >> n;
    double result = fibonacci(n);
    cout << fixed << setprecision(2) << result;
    return 0;
}
// 斐波那契数列 通项公式写出某一项

2.5.2 递归写出某一项

int Fib(int n){
#include <iostream>

using namespace std;

// Fibonacci sequence, recursively calculate a specific term
int Fib(int n){
    if(n==1 || n==2) return 1;
    else return Fib(n - 1) + Fib(n - 2);
}

2.5.3数组写出某一项

#include <iostream>
using namespace std;

int fibonacci(int n) {
    int arr[n+1];
    arr[0] = 0;
    arr[1] = 1;
    for (int i = 2; i <= n; i++) {
        arr[i] = arr[i - 1] + arr[i - 2];
    }
    return arr[n];
}

int main() {
    int n = 10; // 你想要计算的斐波那契数列的项数
    cout << fibonacci(n) << endl; // 输出第n项斐波那契数
    return 0;
}

2.5.4前X项:

#include <iostream>
using namespace std;

void fibonacci(int x) {
    int arr[x];
    arr[0] = 1;  
    arr[1] = 1;
    for (int i = 2; i < x; i++) {
        arr[i] = arr[i-1] + arr[i-2];
    }
    for (int i = 0; i < x; i++) {
        cout << arr[i] << " ";
    }
}

int main() {
    int x;
    cin >> x;
    fibonacci(x);
}
// 斐波那契数列 前X项

2.5.5>其他:

在这里插入图片描述

2.5.6>尾数60一循环

斐波那契数列的个位数,60步的循环

2.6杨辉三角:

题目:

题目描述
给出 n(n≤20),输出杨辉三角的前 n 行。
如果你不知道什么是杨辉三角,可以观察样例找找规律。

输入格式

输出格式

题解:

#include<iostream>
using namespace std;

void printPascalTriangle(int n) {
    int arr[21][21];

    for(int i=0; i<n; i++){
        arr[i][0]=1;
        arr[i][i]=1;
    }

    for(int i=2; i<n; i++){
        for(int j=1; j<i; j++){
            arr[i][j]=arr[i-1][j-1]+arr[i-1][j];
        }
    }

    // 打印输出。在第二层循环的时候不能加{}的原因是因为cout一个
    // 一个点输出的时候每一个都经过了'\n'这个转义字符,所以就是一条竖线
    // 的打印数字
    for(int i=0; i<n; i++){
        for(int j=0; j<=i; j++)
            cout << arr[i][j] << " ";
        cout << "\n";
    }
}

int main(){
    int n;
    cin >> n;
    printPascalTriangle(n);
    return 0;
}

2.7 立方根

#include <iostream>
#include <cmath>

#define PI  3.141593

int main() {
    double a = 4.0, b = 10.0;
    double sum = (4.0 /3.0)* PI * (a * a * a + b * b * b);
    int edge = cbrt(sum);
    std::cout << edge << std::endl;
    return 0;
}
#include <cmath>
#include <iostream>

int main() {
    double r1 = 4.0, r2 = 10.0;
    double v1 = (4.0 / 3.0) * M_PI * pow(r1, 3);
    double v2 = (4.0 / 3.0) * M_PI * pow(r2, 3);
    double total_v = v1 + v2;
    int edge = pow(total_v, 1.0 / 3.0);
    std::cout << edge << std::endl;
    return 0;
}

三、大数计算(高精度)

3.1)乘法

#include<stdio.h>
#include<math.h>
#include<string.h>

int a[10000]; // 存放被乘数的数组
int b[10000]; // 存放乘数的数组
int c[10000]; // 存放结果的数组
char m[10000]; // 存放被乘数的字符串
char n[10000]; // 存放乘数的字符串
int main(){
	int la,lb,lc,i,j,t=0,flag=0,p=0;
	  // la 存放被乘数的长度,lb 存放乘数的长度,lc 存放两者中较大的长度
    // i 和 j 用于循环计数,t、flag、p 用于标记
	scanf("%s %s",m,n);// 读入被乘数和乘数的字符串
	 la=strlen(m); // 计算被乘数的长度
    lb=strlen(n); // 计算乘数的长度
    lc=la>lb?la:lb; // 取两者中较大的长度
    // 将被乘数和乘数的字符串倒序存储到数组中
	//倒序输入数组 
	for(i=0;i<la;i++){
		a[la-i-1]=m[i]-'0';// 将字符转换成数字存储
	}
	for(i=0;i<lb;i++){
		b[lb-i-1]=n[i]-'0';// 将字符转换成数字存储
	}
	int k=la+lb;
	for(j=0;j<lb;j++){
		for(i=0;i<la;i++){
		
			c[i+j]+=a[i]*b[j];
		}
	}
	// 处理进位,将每一位上的数都控制在 0~9 之间
	for(i=0;i<k;i++){
		c[i+1]=c[i]/10+c[i+1];
		c[i]=c[i]%10;
	}
	//while去零 
	while(c[k]==0&&k>=1)k--; 
	for(i=k;i>=0;i--){
		printf("%d",c[i]);
	}
	return 0;
}

cpp

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;

// 大数乘法函数,接受两个字符串形式的大数,返回它们的乘积
string bigNumberMultiply(string num1, string num2) {
    int n1 = num1.size();
    int n2 = num2.size();
    if (n1 == 0 || n2 == 0) return "0";

    // 结果可能的最大长度为n1 + n2
    vector<int> result(n1 + n2, 0);

    // 从右到左,对每一位进行相乘
    for (int i = n1 - 1; i >= 0; i--) {
        for (int j = n2 - 1; j >= 0; j--) {
            int mul = (num1[i] - '0') * (num2[j] - '0');

            // 乘积在res对应的位置加上
            int p1 = i + j, p2 = i + j + 1;
            int sum = mul + result[p2];

            // 进位
            result[p2] = sum % 10;
            result[p1] += sum / 10;
        }
    }

    // 结果前缀可能存的 0(未使用的位)
    int i = 0;
    while (i < result.size() && result[i] == 0)
        i++;

    // 将计算结果转换为字符串
    string str;
    for (; i < result.size(); i++)
        str.push_back(result[i] + '0');

    return str.size() == 0 ? "0" : str;
}

int main() {
    string num1 = "123456789";
    string num2 = "987654321";

    string result = bigNumberMultiply(num1, num2);

    cout << "The result of multiplication is: " << result << endl;

    return 0;
}

3.2)加法

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;

// 大数加法函数,接受两个字符串形式的大数,返回它们的和
string bigNumberAdd(string num1, string num2) {
    // 确保num1不短于num2
    if (num1.size() < num2.size()) {
        swap(num1, num2);
    }

    // 反转字符串,使得从低位开始处理
    reverse(num1.begin(), num1.end());
    reverse(num2.begin(), num2.end());

    int carry = 0; // 进位
    for (int i = 0; i < num1.size(); i++) {
        int temp = num1[i] - '0' + carry;
        if (i < num2.size()) {
            temp += num2[i] - '0';
        }
        num1[i] = temp % 10 + '0'; // 计算当前位的结果
        carry = temp / 10; // 计算进位
    }

    // 如果最后还有进位,添加到结果中
    if (carry != 0) {
        num1 += carry + '0';
    }

    // 将结果反转回正确的顺序
    reverse(num1.begin(), num1.end());

    return num1;
}

int main() {
    string num1 = "123456789123123";
    string num2 = "987654321231231";

    string result = bigNumberAdd(num1, num2);

    cout << "The result of addition is: " << result << endl;

    return 0;
}
#include<bits/stdc++.h>
using namespace std;
string add(string a,string b){
    string s;
    int c=0;
    for(int i=a.size()-1,j=b.size()-1;i>=0||j>=0||c>0;i--,j--){
        if(i>=0)  c+=a[i]-'0';
        if(j>=0)  c+=b[j]-'0';
        
        s+=(c%10)+'0';
        c/=10;
    }
    reverse(s.begin(),s.end());
    return s;
}
int main(){
    string a,b;
    cin>>a>>b;
    cout<<add(a,b);
    return 0;
}

四、进制转换

#include <iostream>
#include <string>
#include <bitset>

using namespace std;

int sumOfDigits(int num, int base) {
    int sum = 0;
    while (num > 0) {
        sum += num % base;
        num /= base;
    }
    return sum;
}

int main() {
    int count = 0;
    int number = 1;

    while (count < 23) {
        string binaryStr = bitset<32>(number).to_string();
        int sumBinary = sumOfDigits(number, 2);
        int sumOctal = sumOfDigits(number, 8);

        if (sumBinary == sumOctal) {
            count++;
        }

        if (count < 23) {
            number++;
        }
    }

    cout << "The 23rd number with equal sum of digits in binary and octal is: " << number << endl;

    return 0;
}

4. 1>高进制----->低进制 与 低进制----->高进制

#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
using namespace std;

// 高进制到低进制的转换
// 参数:原数的字符串形式,原数的进制,目标进制
string highToLow(string num, int base, int targetBase) {
    int decimal = 0; // 十进制中间变量
    string result = ""; // 结果字符串

    // 首先将高进制数转换为十进制
    for (int i = 0; i < num.size(); i++) {
        decimal = decimal * base + (isdigit(num[i]) ? num[i] - '0' : num[i] - 'A' + 10);
    }

    // 然后将十进制数转换为目标进制
    while (decimal) {
        int remainder = decimal % targetBase;
        result += (remainder > 9 ? remainder - 10 + 'A' : remainder + '0');
        decimal /= targetBase;
    }

    // 由于结果是反向生成的,所以需要反转
    reverse(result.begin(), result.end());

    return result;
}

// 低进制到高进制的转换
// 参数:原数的字符串形式,原数的进制,目标进制
string lowToHigh(string num, int base, int targetBase) {
    return highToLow(num, base, targetBase); // 直接调用高进制到低进制的函数,因为这两个函数的实现是对称的
}

int main() {
    cout << highToLow("1A", 16, 10) << endl; // 输出26
    cout << lowToHigh("26", 10, 16) << endl; // 输出1A
    return 0;
}

希望大家多多支持,如果我有错误请指出来。 大家一起进步

五、KMP

5.1 检测有没有

#include <iostream>
#include <string>
#include <vector>

using namespace std;

bool kmpSearch(const string &text, const string &pattern) {
    int m = pattern.size();
    vector<int> lps(m, 0);
    int j = 0;

    // Construct the LPS array
    for (int i = 1; i < m; i++) {
        while (j > 0 && pattern[i] != pattern[j]) {
            j = lps[j - 1];
        }
        if (pattern[i] == pattern[j]) {
            lps[i] = ++j;
        }
    }

    // Perform pattern matching
    int n = text.size();
    j = 0;
    for (int i = 0; i < n; i++) {
        while (j > 0 && text[i] != pattern[j]) {
            j = lps[j - 1];
        }
        if (text[i] == pattern[j]) {
            if (++j == m) {
                return true;  // Match found
            }
        }
    }
    return false;  // No match found
}

int main() {
    string text = "abxabcabcaby";
    string pattern = "abcaby";
    if (kmpSearch(text, pattern)) {
        cout << "Pattern found in the text" << endl;
    } else {
        cout << "Pattern not found in the text" << endl;
    }
    return 0;
}

5.2 检测是在第几位开始的

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int kmpSearch(const string &text, const string &pattern) {
    int m = pattern.size();
    vector<int> lps(m, 0);
    int j = 0;
    int position = -1;

    // Construct the LPS array
    for (int i = 1; i < m; i++) {
        while (j > 0 && pattern[i] != pattern[j]) {
            j = lps[j - 1];
        }
        if (pattern[i] == pattern[j]) {
            lps[i] = ++j;
        }
    }

    // Perform pattern matching
    int n = text.size();
    j = 0;
    for (int i = 0; i < n; i++) {
        while (j > 0 && text[i] != pattern[j]) {
            j = lps[j - 1];
        }
        if (text[i] == pattern[j]) {
            if (++j == m) {
                position = i - m + 1;  // Match found, update position
                break;
            }
        }
    }
    return position;  // Return the position where the match starts
}

int main() {
    string text = "abxabcabcaby";
    string pattern = "abcaby";
    int position = kmpSearch(text, pattern);
    if (position != -1) {
        cout << "Pattern found in the text starting at position " << position << endl;
    } else {
        cout << "Pattern not found in the text" << endl;
    }
    return 0;
}

5.3检测本字符串中有多少次重复最长的字符串段的

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int kmpSearch(const string &text, const string &pattern) {
    int m = pattern.size();
    vector<int> lps(m, 0);
    int j = 0;
    int count = 0;

    // Construct the LPS array
    for (int i = 1; i < m; i++) {
        while (j > 0 && pattern[i] != pattern[j]) {
            j = lps[j - 1];
        }
        if (pattern[i] == pattern[j]) {
            lps[i] = ++j;
        }
    }

    // Perform pattern matching
    int n = text.size();
    j = 0;
    for (int i = 0; i < n; i++) {
        while (j > 0 && text[i] != pattern[j]) {
            j = lps[j - 1];
        }
        if (text[i] == pattern[j]) {
            if (++j == m) {
                count++;  // Match found, update count
                j = lps[j - 1];  // Continue searching for overlapping matches
            }
        }
    }
    return count;  // Return the count of repeated longest substring
}

int main() {
    string text = "abcabcabcabcac";
    string pattern = "abc";
    int count = kmpSearch(text, pattern);
    cout << "The longest repeated substring appears " << count << " times in the text" << endl;
    return 0;
}
  • 16
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你会魔法吗✧(≖ ◡ ≖✿)

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值