杭电1261 -字串数

本文介绍了一种解决典型排列组合问题的方法,重点在于如何处理大数阶乘及大数除法运算。通过C++实现了一个能计算特定排列数量的程序,展示了大数运算的具体实现细节。

一典型的排列问题,不过只需要给出具体的排列的数就可以了,不需要给出具体的排列!数据不是很大,就直接算吧!

#include <iostream>
#include <string.h>
#define NUM1 26+1
#define MAX 400
using namespace std;
int all[MAX];
void mul(int sum)
{
    int i,j;
    int carry;
    memset(all,0,sizeof(all));
    all[0]=1;
    for(i=1;i<=sum;i++)
    {
        carry=0;
        for(j=0;j<MAX;j++)
        {
            all[j]=all[j]*i+carry;
            carry=0;
            if(all[j]>10)
            {
                carry=all[j]/10;
                all[j]%=10;
            }
        }
    }
    return ;
}
int mul1(int m)
{
    int i,sum=1;
    for(i=1;i<=m;i++)
        sum*=i;
    return sum;
}

void div(int *all,int a)
{
    int i;
    long long int quotient=0;
    for(i=MAX-1;i>=0;i--)
        if(all[i]!=0)
            break;
    for(;i>=0;i--)
    {
        quotient =quotient*10 + all[i];
        all[i] = quotient/a;
        quotient %= a;
    }

   return ;
}
int main()
{
    int m,sum;
    int a[NUM1];
    while(cin>>m,m)
    {
        int i;
        sum=0;
        memset(a,0,sizeof(a));
        for(i=1;i<=m;i++)
        {
            cin>>a[i];
            sum+=a[i];
        }

        mul(sum);

        for(i=1;i<=m;i++)
        {
            div(all,mul1(a[i]));
        }
    for(i=MAX-1;i>=0;i--)
        if(all[i]!=0) break;
    for(;i>=0;i--)
        cout<<all[i];
    cout<<endl;
    }
    return 0;
}

这里涉及到了,大数的阶乘,和大数除以一个小数的思路!可以细细体会一下!

<think>嗯,用户问的是如何在C语言中实现查询字符串个的功能。首先,我需要明确用户的需求。这里的“查询字串”可能指的是在一个主字符串中查找某个子字符串出现的次。比如,在"ababaab"中查找"aba",应该返回出现次,可能是1次或者2次,这取决于是否允许重叠。 接下来,我得考虑如何用C语言来实现这个功能。首先,主函的结构应该包括输入主字符串和子字符串,然后调用一个查找函,最后输出结果。不过,用户可能只需要核心的查找逻辑,所以可能需要重点解释查找函的部分。 然后是算法部分。常见的做法是遍历主字符串,逐个字符检查是否与子字符串的开头匹配。如果匹配,则继续检查后续的字符是否完全匹配。如果完全匹配,则计数器加一,并且根据是否允许重叠来决定下一次开始查找的位置。例如,如果允许重叠,在找到一次后,主字符串的指针只需前进一位;如果不允许,则需要跳过整个子字符串的长度。不过,通常这类问题允许重叠,比如在"aaaa"中找"aa",应该返回3次。 接下来,我需要考虑如何实现这个循环。使用两个指针,一个遍历主字符串,另一个遍历子字符串。当主字符串的当前字符与子字符串的第一个字符匹配时,进入内层循环检查后续字符是否全部匹配。如果全部匹配,计数器加一,然后主字符串的指针前进一位继续查找。如果中途不匹配,则跳出内层循环,主字符串指针也前进一位。 需要注意的是边界条件,比如主字符串剩余的字符长度是否足够容纳子字符串。例如,当主字符串剩余长度小于子字符串长度时,可以直接结束循环,避免越界访问。 然后,编写代码的大致步骤是:定义函,接收主字符串和子字符串的指针,返回整类型的计数。在函内部,初始化计数器为0,获取子字符串的长度。如果子字符串长度为0,可能直接返回0或者处理错误情况。然后循环主字符串,直到主字符串剩余长度不足。 在代码实现中,可能需要使用strlen函获取字符串长度,但要注意效率问题,因为strlen是O(n)的时间复杂度,如果在大循环中频繁调用会影响性能。不过,对于一般的应用来说,这可能不是问题。或者可以在循环外部计算主字符串和子字符串的长度,避免重复计算。 另外,字符比较部分,可以用循环逐个比较,或者使用strncmp函来比较指定长度的子串是否匹配。使用strncmp可能更简洁,但需要传递正确的参,即从主字符串当前位置开始的子字符串长度的部分,和子字符串比较。 例如,使用strncmp(main_str + i, sub_str, sub_len) == 0来判断是否匹配。如果匹配,则计数器加一,并且主字符串的索引i可以增加1(允许重叠)或者sub_len(不允许重叠)。这里用户可能需要允许重叠的情况,所以应该增加1。 同时,需要处理子字符串长度为0的情况,避免除以零错误或者其他问题。例如,在计算主字符串剩余长度时,主字符串长度减去子字符串长度,如果子字符串长度为0,会导致错误,所以需要在函开始时检查子字符串长度是否为0,如果是,返回0或者错误码。 另外,用户可能在输入时需要注意字符串的输入方式,比如使用fgets来避免缓冲区溢出,或者处理可能的输入错误。但核心的查找函可能不需要处理这些,而是假设传入的是有效的字符串。 测试用例也是需要考虑的。例如,主字符串为"abababa",子字符串为"aba",正确结果应该是3次(允许重叠的情况下)。或者主字符串为空,子字符串非空,返回0;子字符串为空,返回0等等。 可能还需要考虑大小写是否敏感的问题,但通常默认是敏感的,所以代码中不需要特别处理,除非用户有特别需求。 最后,将整个思路整理成代码,并添加注释,说明每一步的作用。同时,提供示例代码和测试案例,帮助用户理解如何使用这个函。</think>在 C 语言中实现查询子字符串出现次的核心思路是:通过循环遍历主字符串,逐个检查是否存在与子字符串完全匹配的连续字符序列。以下是实现步骤与代码示例: ```c #include <stdio.h> #include <string.h> // 查找子字符串出现次的函 int count_substring(const char* main_str, const char* sub_str) { int count = 0; int sub_len = strlen(sub_str); int main_len = strlen(main_str); // 边界条件:子字符串为空或主字符串比子字符串短 if (sub_len == 0 || main_len < sub_len) return 0; // 遍历主字符串(只需遍历到 main_len - sub_len 的位置) for (int i = 0; i <= main_len - sub_len; i++) { // 使用 strncmp 比较指定长度的字符串 if (strncmp(main_str + i, sub_str, sub_len) == 0) { count++; } } return count; } int main() { char main_str[100], sub_str[100]; printf("请输入主字符串:"); fgets(main_str, sizeof(main_str), stdin); main_str[strcspn(main_str, "\n")] = '\0'; // 去除换行符 printf("请输入子字符串:"); fgets(sub_str, sizeof(sub_str), stdin); sub_str[strcspn(sub_str, "\n")] = '\0'; int result = count_substring(main_str, sub_str); printf("子字符串出现的次:%d\n", result); return 0; } ``` ### 代码说明 1. **函**:`count_substring` 接收主字符串和子字符串的指针 2. **边界处理**: - 子字符串长度为 0 时直接返回 0 - 主字符串比子字符串短时直接返回 0 3. **核心逻辑**: - 通过 `for` 循环遍历主字符串,`i <= main_len - sub_len` 确保不会越界 - 使用 `strncmp(main_str + i, sub_str, sub_len)` 进行定长比较 4. **重叠匹配**:本实现支持重叠匹配(如 "aaaa" 中找 "aa" 会返回 3 次) ### 示例测试 | 主字符串 | 子字符串 | 输出结果 | |----------------|----------|----------| | "abababa" | "aba" | 3 | | "hello world" | "lo" | 1 | | "aaaaa" | "aa" | 4 | | "abc" | "xyz" | 0 | ### 时间复杂度 - 最优情况:$O(n)$(首字符不匹配时直接跳过) - 最差情况:$O(n \times m)$(需要完全遍历主字符串并进行全子串比较) (其中 n 为主字符串长度,m 为子字符串长度) 实际开发中如需高频查询,可考虑使用更高效的算法(如 KMP 算法),其时间复杂度为 $O(n + m)$。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值