在圆周率中寻找字符串

#老师说可以尝试一下编写这样的代码,编写出来平时分直接有95分!!!好好好,我就是想学习一下这样的代码怎么写,绝对不是为了绩点!绝对不是!(老实巴交)#

在找资料的时候找到了一个有意思的网页,好像就是我想要的:圆周率查询-生日数字在圆周率中排列第几位 - 在线工具 (wqtool.com)

可惜这个网页没有代码。那我们就来搓一搓这个代码。

可不可以直接在一个程序中先把圆周率找出来储存一下,再通过字符串筛查的方法直接搜索呢?

        分析一下。

                1,且不说先把圆周率找出来要算多久,光是小数点后几千万位的数字的储存就挺吓人的。(也许用字符串数组可以储存)

                2,且假设小数点后几千万卫的数字可以储存,那用什么方法搜索呢?目前我已知最快的字符串搜索算法--KMP.。那么已知,KMP算法的时间复杂度为O(m+n),且估算为线性时间复杂度,那么假设圆周率后有e8位。emmmm这么一算好像KMP可以实现。

                3,程序中的圆周率计算。(难点)编程计算Pi(π)的N种方法_使用级数求pi的值的程序-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/s170262941/article/details/11123945?spm=1001.2014.3001.5506(参考别人写的珍贵资料)

转变思路?!

把圆周率存在另一个文件中,可以直接从这个文件中KMP一下,这样就不用再算圆周率了。这样可以直接得到答案,嗯感觉要好很多。

那么去哪里弄圆周率文件呢?或许我们可以去网上直接copy一下......

当然也有其他办法--y-cruncher--一个生成pi的工具。----CPU测试相关工具搜集_y-cruncher下载-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/zyhse/article/details/113242153

y-cruncher - A Multi-Threaded Pi Program (numberworld.org)icon-default.png?t=N7T8http://numberworld.org/y-cruncher/

(这个文章里也有代码)

之后就是KMP了(原创)详解KMP算法 - 孤~影 - 博客园 (cnblogs.com)icon-default.png?t=N7T8https://www.cnblogs.com/yjiyjige/p/3263858.html

ok工具齐全,敲代码!

圆周率查找字符串1.0

#include<iostream>
#include<string>
#include<fstream>
using namespace std;
void get_next(string T, int next[])
{
    int i=0,j=-1;
    next[0]=-1;
    while (i<T.length())
    {
        if(j==-1||T[i]==T[j])
        {
            ++i;
            ++j;
            next[i]=j;
        }
        else j=next[j];
    }
}
int Index_KMP(string S,string T,int pos)
{
 
    int i = pos, j = -1;
    int next[T.length()+1];
    get_next(T,next);
    while(i<(int)S.length() && j<(int)T.length())
    {
        if(j==-1||S[i]==T[j])
        {
            ++i;
            ++j;
        }
        else j=next[j];
    }
    if(j==(int)T.length()) return i-T.length();
    else return 0;
}
int main()
{
    string data,b;
    cout<<"输入你要寻找的字串:";
    cin>>b;
    ifstream infile;
    infile.open("Pi-file.txt");
    infile >> data;
    cout<<"在Pi小数点后"<<Index_KMP(data,b,-1)-1<<"位";
    infile.close();                 
    return 0;
}

直接用KMP的代码去查找就好了。

效果展示

这里我的“Pi-file.txt"里存储了圆周率后十亿位。大概能查找到九位数的字符串。

然后再1.0版本的基础上做了一些更改。

写了一个能查找到字符串出现第二次与第一次相差位次的版本。

圆周率查找字符串2.0

#include<iostream>
#include<string>
#include<fstream>
using namespace std;
long long fir=0,sec=0;
void get_next(string T, long long next[])
{
    int i=0,j=-1;
    next[0]=-1;
    while (i<T.length())
    {
        if(j==-1||T[i]==T[j])
        {
            ++i;
            ++j;
            next[i]=j;
        }
        else j=next[j];
    }
}
int Index_KMP(string S,string T,long long pos)
{
  
    long long i = pos;
	long long j = -1;
    long long next[T.length()+1];
    get_next(T,next);
    while(i<(int)S.length() && j<(int)T.length())
    {
        if(j==-1||S[i]==T[j])
        {
            ++i;
            ++j;
        }
        else j=next[j];
    }
    if(i>=(int)S.length())
    return 0;
    fir=i-T.length();
    j=-1;
    while(i<(int)S.length() && j<(int)T.length())
    {
        if(j==-1||S[i]==T[j])
        {
            ++i;
            ++j;
        }
        else j=next[j];
    }
    if(i>=(int)S.length())
    return 0;
    sec=i-T.length(); 
    if(j==(int)T.length()) return 0;
    else return 0;
}
int main()
{
    string data,b;
    cout<<"输入你要寻找的字串:";
    cin>>b;
    ifstream infile;
    infile.open("Pi-file.txt");
    infile >> data;
    Index_KMP(data,b,-1);
    if(fir)	{
    cout<<"第一次出现在Pi小数点后"<<fir-1<<"位"<<endl;
    if(sec){
	cout<<"第二次出现在Pi小数点后"<<sec-1<<"位"<<endl;
	cout<<"第二次与第一次相差"<<sec-fir<<"位"<<endl; 
	
	}
	else{
	cout<<"在十亿位次内没有找到该字符串"<<endl; 
	} 
	}
    
	else 
	cout<<"在十亿位次内没有找到该字符串"<<endl;
    infile.close();                 
    return 0;
}

效果展示

当然了不仅可以找到所在位置,也可以将这一部分的字符串展示出来,加一个小小的输出就好了。

再加个循环,加个停顿,加个颜色展示。OK!

圆周率查找字符串3.0

#include<iostream>
#include<string>
#include<fstream>
using namespace std;
#define RED "\033[0;32;31m"
#define WHITE "\033[1;37m"
long long fir=0,sec=0;
void get_next(string T, long long next[])
{
    int i=0,j=-1;
    next[0]=-1;
    while (i<T.length())
    {
        if(j==-1||T[i]==T[j])
        {
            ++i;
            ++j;
            next[i]=j;
        }
        else j=next[j];
    }
}
int Index_KMP(string S,string T,long long pos)
{
  
    long long i = pos;
	long long j = -1;
    long long next[T.length()+1];
    get_next(T,next);
    while(i<(int)S.length() && j<(int)T.length())
    {
        if(j==-1||S[i]==T[j])
        {
            ++i;
            ++j;
        }
        else j=next[j];
    }
    if(i>=(int)S.length())
    return 0;
    fir=i-T.length();
    j=-1;
    while(i<(int)S.length() && j<(int)T.length())
    {
        if(j==-1||S[i]==T[j])
        {
            ++i;
            ++j;
        }
        else j=next[j];
    }
    if(i>=(int)S.length())
    return 0;
    sec=i-T.length(); 
    if(j==(int)T.length()) return 0;
    else return 0;
}
int main()
{
	while(1)
	{
	fir=0,sec=0;
    string data,b;
    cout<<"输入你要寻找的字串:";
    cin>>b;
    ifstream infile;
    infile.open("Pi-file.txt");
    infile >> data;
    Index_KMP(data,b,-1);
    if(fir)	{
    cout<<"第一次出现在Pi小数点后"<<fir-1<<"位"<<endl;
    cout<<"字符串展示: "; 
    for(long long ss=fir-10;ss<=fir+10+b.length() ;ss++)
	{
		if(ss>=fir&&ss<fir+b.length() )
		{
			cout<<RED;
			cout<<data[ss];
			continue; 
		}
		cout<<WHITE;
		cout<<data[ss];
	 }
	 cout<<endl; 
    if(sec){
	cout<<"第二次出现在Pi小数点后"<<sec-1<<"位"<<endl;
	    cout<<"字符串展示: ";
    for(long long ss=sec-10;ss<=sec+10+b.length() ;ss++)
	{
		if(ss>=sec&&ss<sec+b.length() )
		{
			cout<<RED;
			cout<<data[ss];
			continue; 
		}
		cout<<WHITE;
		cout<<data[ss];
		
	 }
	 cout<<endl; 
	cout<<"第二次与第一次相差"<<sec-fir<<"位"<<endl; 
	
	}
	else{
	cout<<"在十亿位次内没有找到该字符串"<<endl; 
	} 
	}
    
	else 
	cout<<"在十亿位次内没有找到该字符串"<<endl;
    infile.close();                 
    system("Pause");
}
}

效果展示

完美!

再思考一下......

因为我的“Pi-file.txt"储存了圆周率后十亿位数字,占了1GB的内存,所以整个程序运行下来会很慢。当然也因为我的文件里只有十亿位小数,我们用来查找13位的学号可能会查找不出来。如果想要查找更长的字符串,那我们的文件的储存也要足够。比如文件里存储一百亿位数字?一千亿?。

参考文献:

编程计算Pi(π)的N种方法_使用级数求pi的值的程序-CSDN博客

KMP实现圆周率PI中找字串-CSDN博客

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值